Сообщение PyLint: logging-format-interpolation

161

Для следующего кода:

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

pylint выдает следующее предупреждение:

logging-format-interpolation (W1202):

Используйте форматирование% в функциях ведения журнала и передайте параметры% в качестве аргументов. Используется, когда оператор ведения журнала имеет форму вызова «logging. (Format_string.format (format_args ...))». Такие вызовы должны использовать форматирование%, но оставить интерполяцию для функции регистрации, передав параметры в качестве аргументов.

Я знаю, что могу отключить это предупреждение, но я хотел бы понять это. Я предположил, что использование format()является предпочтительным способом распечатки операторов в Python 3. Почему это не так для операторов логгера?

pfnuesel
источник

Ответы:

204

Это неверно для оператора logger, потому что он опирается на прежний формат "%", такой как строка, чтобы обеспечить ленивую интерполяцию этой строки, используя дополнительные аргументы, переданные вызову logger. Например, вместо того, чтобы делать:

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

ты должен сделать

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

поэтому строка будет интерполироваться только в том случае, если сообщение действительно отправлено.

Вы не можете воспользоваться этой функциональностью при использовании .format().


Согласно разделу по оптимизацииlogging документов:

Форматирование аргументов сообщения откладывается до тех пор, пока его нельзя избежать. Однако вычисление аргументов, передаваемых методу регистрации, также может быть дорогостоящим, и вы можете избежать этого, если регистратор просто выбросит ваше событие.

sthenault
источник
4
@pfnuesel, .format () раскрывается перед вызовом logger.error, а «ленивая интерполяция» означает, что расширение выполняется только при необходимости (например, сообщение фактически отображается где-то)
sthenault
10
Есть хорошая ссылка для того, чтобы эта ленивая оценка была предпочтительна и имела значение? Я не смог найти ни одного в PEP282 или библиотеке журналов
culix
25
Но значит ли это, что у нас будут проблемы с обслуживанием нашего кода позже? Позже мы будем «рекомендованы» компанией Pylint для перехода к .format()стилю в какой-то момент, потому что loggingон обновился? Я спрашиваю, потому что меня больше интересует ремонтопригодность, чем передовая скорость, по крайней мере, для большинства задач.
Майк Уильямсон
3
@MikeWilliamson: я думаю, что это сообщение является предупреждением, потому что возможны побочные эффекты, но вы можете смело игнорировать его.
Saihtamtellim
5
Хотя большая часть мотивации этого предупреждения связана с производительностью (т. Е. Если оператор журнала не генерируется, тогда затраты на интерполяцию сохраняются), стоит отметить, что во многих (возможно, большинстве) приложениях затраты на производительность незначительны. См. Github.com/PyCQA/pylint/issues/2395 и github.com/PyCQA/pylint/issues/2354
Адам Паркин
23

Может быть, это разница во времени может помочь вам.

Следующее описание не является ответом на ваш вопрос, но может помочь людям.

Для pylint 2.4: Есть 3 варианта входа стиль в .pylintrcфайле: old, new,fstr

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)

Примечание : вы не можете использовать, .format()даже если вы выберите newопцию.

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 .

mustafagok
источник
2
Вы можете добавить "python.linting.pylintArgs": ["--logging-format-style=old"]в файл vscode / settings.json. документы
mustafagok
2
в Пилинте 2.3.1: optparse.OptionValueError: option logging-format-style: invalid value: 'fstr', should be in ['old', 'new']обновление до последней Пилинта (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!
Альпер
4

По моему опыту, более веская причина, чем оптимизация (для большинства случаев использования) для ленивой интерполяции, заключается в том, что она прекрасно работает с агрегаторами журналов, такими как Sentry.

Рассмотрим сообщение «пользователь вошел в систему». Если вы интерполируете пользователя в строку формата, у вас будет столько разных сообщений журнала, сколько есть пользователей. Если вы используете ленивую интерполяцию, подобную этой, агрегатор журналов может более разумно интерпретировать это как одно и то же сообщение журнала с кучей разных экземпляров.

Тристан Крокетт
источник