Повідомлення PyLint: журнал-формат-інтерполяція


161

Для наступного коду:

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

pylint видає таке попередження:

журнал-формат-інтерполяція (W1202):

Використовуйте% форматування у функціях реєстрації та передайте% параметри як аргументи, що використовуються, коли оператор журналу має форму виклику "logging. (Format_string.format (format_args ...))". Такі виклики повинні використовувати замість форматування%, але залишати інтерполяцію функції реєстрації, передаючи параметри як аргументи.

Я знаю, що можу вимкнути це попередження, але хотів би його зрозуміти. Я припускав, що використання format()є кращим способом роздрукувати заяви на Python 3. Чому це не відповідає дійсності операторів реєстратора?

Відповіді:


203

Це неправда для оператора реєстратора, тому що він покладається на колишній формат "%", як рядок, щоб забезпечити ледачу інтерполяцію цієї рядки, використовуючи додаткові аргументи, надані для виклику реєстратора. Наприклад, замість того, щоб робити:

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

ви повинні зробити

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

тому рядок буде інтерпольований лише у тому випадку, якщо повідомлення фактично випромінюється.

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


У розділі Оптимізаціяlogging документів:

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


4
@pfnuesel, .format () розширюється перед викликом до logger.error, тоді як "ледача інтерполяція" означає розширення, лише якщо потрібно (наприклад, повідомлення фактично десь відображається)
sthenault

10
Чи є корисна посилання на те, щоб цю ліниву оцінку віддали перевагу та змінили? Я не зміг знайти його в PEP282 або бібліотеці журналів
culix

25
Але чи це означає лише те, що пізніше у нас виникнуть проблеми з технічним обслуговуванням нашого коду? Чи пізніше нам буде рекомендований пілінт, щоб перейти до .format()стилю в якийсь момент, оскільки loggingоновився? Я запитую, тому що мене більше цікавить ремонтопридатність, ніж мене, швидкість кровотоку, принаймні для більшості завдань.
Майк Вільямсон

3
@MikeWilliamson: Я думаю, що це повідомлення є попередженням, оскільки можливі побічні ефекти, але ви можете сміливо ігнорувати його.
saihtamtellim

5
Хоча велика частина мотивації за попередженням залежить від продуктивності (тобто: якщо протокол журналу не випромінюється, то вартість інтерполяції економиться), варто відзначити, що в багатьох (можливо, більшості) додаткових витратах незначна. Дивіться: github.com/PyCQA/pylint/isissue/2395 та github.com/PyCQA/pylint/isissue/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 .


2
ви можете додати "python.linting.pylintArgs": ["--logging-format-style=old"]до файла vscode / settings.json. docs
mustafagok

2
у 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!
Альпер

4

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

Розгляньте повідомлення журналу "зареєстрований користувач". Якщо ви інтерполюєте користувача в рядок формату, у вас є стільки різних повідомлень журналу, скільки є користувачів. Якщо ви використовуєте подібну ледачу інтерполяцію, агрегатор журналів може більш розумно інтерпретувати це як те саме повідомлення журналу з купою різних примірників.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.