PyLint 消息:记录格式插值

Posted

技术标签:

【中文标题】PyLint 消息:记录格式插值【英文标题】:PyLint message: logging-format-interpolation 【发布时间】:2016-04-09 18:08:57 【问题描述】:

对于以下代码:

logger.debug('message: '.format('test'))

pylint 产生以下警告:

记录格式插值 (W1202):

在日志记录函数中使用 % 格式并将 % 参数传递为 参数 当日志语句的调用形式为 “记录。(format_string.format(format_args ...))”。这样的 调用应改用 % 格式,但将插值留给 通过将参数作为参数传递来记录函数。

我知道我可以关闭此警告,但我想了解它。我假设使用format() 是在 Python 3 中打印语句的首选方式。为什么对于 logger 语句不适用?

【问题讨论】:

【参考方案1】:

logger 语句不是这样,因为它依赖于以前的“%”格式(如字符串),使用给予 logger 调用的额外参数来提供此字符串的惰性插值。例如,不要这样做:

logger.error('oops caused by %s' % exc)

你应该这样做

logger.error('oops caused by %s', exc)

所以只有在实际发出消息时才会对字符串进行插值。

您在使用.format() 时无法享受此功能。


根据logging 文档的Optimization 部分:

消息参数的格式被推迟到无法避免为止。但是,计算传递给 logging 方法的参数也可能很昂贵,如果 logger 只是丢弃您的事件,您可能希望避免这样做。

【讨论】:

@pfnuesel,.format() 在调用 logger.error 之前被扩展,而“惰性插值”意味着仅在需要时才进行扩展(例如,消息实际上显示在某处) 这种懒惰的评估是否有很好的参考价值并有所作为?我在PEP282 或the logging library 中找不到一个 但这只是意味着我们以后的代码会出现维护问题吗?我们以后是否会因为 logging 已升级而在某个时候被 pylint “推荐”以迁移到 .format() 样式?我之所以这么问,是因为我对可维护性比对前沿速度性能更感兴趣,至少对于大多数任务而言。 @MikeWilliamson :我认为此消息是一个警告,因为可能存在副作用,但您可以放心地忽略它。 虽然警告背后的大部分动机是围绕性能(即:如果未发出日志语句,则节省插值成本),值得注意的是,在许多(可以说是大多数)应用程序中性能成本可以忽略不计。请参阅:github.com/PyCQA/pylint/issues/2395 和 github.com/PyCQA/pylint/issues/2354【参考方案2】:

也许这个time differences 可以帮助你。

以下描述不是您问题的答案,但它可以帮助人们。

如果您想使用 fstrings(文字字符串插值)进行日志记录,则可以使用 disable=logging-fstring-interpolation.pylintrc 文件中禁用它,请参阅:related issue and comment。

您也可以禁用logging-format-interpolation


对于 pylint 2.4:

.pylintrc 文件中的日志记录样式有 3 个选项:oldnewfstr

fstr 选项在2.4 中添加并在2.5 中删除

来自.pylintrc 文件(v2.4)的描述:

[LOGGING]

# Format style used to check logging format string. `old` means using %
# formatting, `new` is for `` formatting,and `fstr` is for f-strings.
logging-format-style=old

对于 (logging-format-style=old):

foo = "bar"
self.logger.info("foo: %s", foo)

对于 (logging-format-style=new):

foo = "bar"
self.logger.info("foo: ", foo)
# OR
self.logger.info("foo: foo", foo=foo)

注意:即使您选择了new 选项,您也可以使用.format()

pylint 仍然为此代码提供相同的 警告

self.logger.info("foo: ".format(foo))  # W1202
# OR
self.logger.info("foo: foo".format(foo=foo))  # W1202

对于 fstr (logging-format-style=fstr):

foo = "bar"
self.logger.info(f"foo: foo")

我个人更喜欢 fstr 选项,因为PEP-0498。

【讨论】:

你可以在 vscode/settings.json 文件中添加"python.linting.pylintArgs": ["--logging-format-style=old"]。 docs 在 pylint 2.3.1 中:optparse.OptionValueError: option logging-format-style: invalid value: 'fstr', should be in ['old', 'new'] 升级到最新的 pylint (2.4.4) 修复了这个问题。 我遇到以下错误:Try installing a more recent version of python-pylint, and please open a bug report if the issue persists in t\ he latest release. Thanks! 更新:fstr 日志记录格式选项已删除,在 .pylintrc 中设置 disable=logging-fstring-interpolation。 github.com/PyCQA/pylint/issues/3570 f 字符串的较短用法是 self.logger.info(f"foo=")。无需将变量或表达式拼写两次。【参考方案3】:

根据我的经验,惰性插值比优化(对于大多数用例)更令人信服的原因是它可以很好地与 Sentry 等日志聚合器配合使用。

考虑一条“用户登录”的日志消息。如果您将用户插入到格式字符串中,您将拥有与用户数量一样多的不同日志消息。如果你像这样使用惰性插值,日志聚合器可以更合理地将其解释为具有一堆不同实例的同一日志消息。

【讨论】:

是的,这是惰性日志记录参数格式的最强论据【参考方案4】:

可能是几年后,但前几天不得不处理这个问题,我变得简单了;只是在记录器之前格式化了字符串。

message = 'message: '.format('test')
logger.debug(message)

这样就无需更改日志中的任何设置,如果以后希望更改为正常打印,则无需更改格式或代码。

【讨论】:

如果有人投反对票,请至少提供评论说明为什么或为什么不。 Tristan Crockett 的回答是不使用您的方法的最佳理由,即使它起初看起来更实用。 解决关于如何删除警告的问题。是无法正确解析和连接字符串的记录器。并且应该记住,需要设置他想要记录的程序员

以上是关于PyLint 消息:记录格式插值的主要内容,如果未能解决你的问题,请参考以下文章

机器学习数据预处理之缺失值:插值法填充+ lagrange插值+拉格朗日插值

插值表达式和 JSON 字符串格式化运用

使用 Spring 4 和消息插值配置在 ConstraintValidator 中注入存储库

Matlab中插值函数

20190710记录2:插值图像拼接融合记录

Dicom影像缩放插值