python PyLint消息:测井格式插值

5us2dqdw  于 2022-12-10  发布在  Python
关注(0)|答案(6)|浏览(181)

对于以下代码:

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

pylint会产生下列警告:

记录格式插值(W1202):

在日志函数中使用%格式并将%参数作为参数传递当日志语句的调用形式为“logging.(format_string.format(format_args...))"时使用。此类调用应改用%格式,但通过将参数作为参数传递,将插值留给日志函数。
我知道我可以关闭这个警告,但是我想理解它。我假设在Python 3中使用format()是打印语句的首选方式。为什么对于logger语句不是这样呢?

wsewodh2

wsewodh21#

这对于logger语句是不正确的,因为它依赖于以前的“%”格式,如字符串,以使用为logger调用提供的额外参数来提供此字符串的惰性插值。例如,而不是执行:

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

你应该做的

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

因此只有在实际发出消息时才对字符串进行插值。
在使用.format()时,您无法使用此功能。
根据logging文档的优化部分:
消息参数的格式化被推迟到无法避免的时候。但是,计算传递给日志方法的参数也可能是昂贵的,如果记录器会丢弃您的事件,您可能希望避免这样做。

knpiaxh1

knpiaxh12#

也许这个time differences能帮到你。
下面的描述不是你问题的答案,但它可以帮助人们。
如果你想使用fstrings(Literal String Interpolation)进行日志记录,那么你可以从.pylintrc文件中用disable=logging-fstring-interpolation禁用它,参见:相关问题和意见。
您也可以禁用logging-format-interpolation

对于pylint 2.4:

.pylintrc文件中有3个记录样式选项:oldnewfstr
2.4中添加了fstr选项,在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

对于fstrlogging-format-style=fstr):

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

就我个人而言,我更喜欢fstr选项,因为PEP-0498

41ik7eoe

41ik7eoe3#

根据我的经验,对于惰性插值,比优化(对于大多数用例)更有说服力的原因是它可以很好地与像Sentry这样的日志聚合器配合使用。
考虑一个“用户已登录”的日志消息。如果你将用户插入到格式字符串中,你就有了和用户一样多的不同日志消息。如果你像这样使用惰性插入,日志聚合器可以更合理地将其解释为具有一堆不同示例的相同日志消息。

wnrlj8wa

wnrlj8wa4#

“logging-format-interpolation(W1202)”是pylint的另一个错误建议(与pep 8的许多建议一样)。F-管柱被描述为慢于%,但你检查过吗?使用500_000旋转的测井,f-管柱与% -〉f-管柱:23.01秒,%:25.43秒。
因此,使用f-string测井比%快。当您查看测井源代码时:日志记录工厂()-〉类LogRecord()-〉home made等价于格式()
密码:

import logging
import random
import time

loops = 500_000
r_fstr = 0.0
r_format = 0.0

def test_fstr():
    global loops, r_fstr
    for i in range(0, loops):
        r1 = time.time()
        logging.error(f'test {random.randint(0, 1000)}')
        r2 = time.time()
        r_fstr += r2 - r1

def test_format():
    global loops, r_format
    for i in range(0 ,loops):
        r1 = time.time()
        logging.error('test %d', random.randint(0, 1000))
        r2 = time.time()
        r_format += r2 - r1

test_fstr()
test_format()
print(f'Logging f-string:{round(r_fstr,2)} sec. , %:{round(r_format,2)} sec.')
sauutmhj

sauutmhj5#

下面是一个示例,说明为什么在测井中使用%s而不是f字符串更好。

>>> import logging
>>> logging.basicConfig(level=logging.INFO)
>>> logger = logging.getLogger('MyLogger')
>>>
>>> class MyClass:
...     def __init__(self, name: str) -> None:
...         self._name = name
...     def __str__(self) -> str:
...         print('GENERATING STRING')
...         return self._name
...
>>> c = MyClass('foo')
>>> logger.debug('Created: %s', c)
>>> logger.debug(f'Created: {c}')
GENERATING STRING

灵感源自Python 3.7 logging: f-strings vs %

pvcm50d1

pvcm50d16#

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

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

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

相关问题