Mensaje de PyLint: logging-format-interpolation

161

Para el siguiente código:

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

pylint produce la siguiente advertencia:

interpolación de formato de registro (W1202):

Use el formato% en las funciones de registro y pase los parámetros% como argumentos Se utiliza cuando una declaración de registro tiene una forma de llamada de "registro. (Format_string.format (format_args ...))". Dichas llamadas deberían usar el formato%, pero dejar la interpolación a la función de registro pasando los parámetros como argumentos.

Sé que puedo desactivar esta advertencia, pero me gustaría entenderla. Supuse que usar format()es la forma preferida de imprimir declaraciones en Python 3. ¿Por qué esto no es cierto para las declaraciones de registrador?

pfnuesel
fuente

Respuestas:

204

No es cierto para la declaración del registrador porque se basa en el formato anterior "%" como cadena para proporcionar una interpolación diferida de esta cadena utilizando argumentos adicionales dados a la llamada del registrador. Por ejemplo, en lugar de hacer:

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

deberías hacer

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

por lo que la cadena solo se interpolará si el mensaje se emite realmente.

No puede beneficiarse de esta funcionalidad cuando lo usa .format().


Según la sección de optimización de los loggingdocumentos:

El formato de los argumentos del mensaje se difiere hasta que no se pueda evitar. Sin embargo, calcular los argumentos pasados ​​al método de registro también puede ser costoso, y es posible que desee evitar hacerlo si el registrador simplemente descarta su evento.

sthenault
fuente
44
@pfnuesel, .formato () se expande antes de la llamada a logger.error, mientras que la expansión de interpolación significa "perezosa" se realiza sólo si es necesario (por ejemplo, en alguna parte del mensaje se muestra realmente)
sthenault
10
¿Existe una buena referencia para que esta evaluación perezosa sea preferida y marque la diferencia? No pude encontrar uno en PEP282 o en la biblioteca de registro
culix
25
Pero, ¿significa esto que tendremos problemas de mantenimiento con nuestro código más adelante? ¿Seremos "recomendados" luego por pylint para pasar al .format()estilo en algún momento porque se loggingha actualizado? Pregunto porque estoy más interesado en la mantenibilidad que en el rendimiento de velocidad de punta, al menos para la mayoría de las tareas.
Mike Williamson
3
@MikeWilliamson: Creo que este mensaje es una advertencia porque hay posibles efectos secundarios, pero puede ignorarlo con seguridad.
saihtamtellim
55
Si bien gran parte de la motivación detrás de la advertencia está relacionada con el rendimiento (es decir: si no se emite una declaración de registro, entonces se ahorra el costo de interpolación), vale la pena señalar que en muchas (posiblemente la mayoría) de las aplicaciones, el costo de rendimiento es insignificante. Ver: github.com/PyCQA/pylint/issues/2395 y github.com/PyCQA/pylint/issues/2354
Adam Parkin
23

Quizás esta vez las diferencias puedan ayudarte.

La siguiente descripción no es la respuesta a su pregunta, pero puede ayudar a las personas.

Para pylint 2.4: Existen 3 opciones para iniciar sesión en el estilo de .pylintrcarchivo: old, new,fstr

fstropción agregada en 2.4 y eliminada en 2.5

Descripción del .pylintrcarchivo (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

para viejo ( logging-format-style=old):

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

para new ( logging-format-style=new):

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

Nota : puede no utilizar .format()incluso si selecciona newla opción.

Pylint todavía da la misma advertencia para este código:

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

para fstr ( logging-format-style=fstr):

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

Personalmente, prefiero la opción fstr debido a PEP-0498 .

mustafagok
fuente
2
puede agregarlo "python.linting.pylintArgs": ["--logging-format-style=old"]al archivo vscode / settings.json. docs
mustafagok
2
en pylint 2.3.1: la optparse.OptionValueError: option logging-format-style: invalid value: 'fstr', should be in ['old', 'new']actualización a la última pylint (2.4.4) solucionó esto.
Florian Castellane
Estoy teniendo siguiente error: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!
Alper
4

En mi experiencia, una razón más convincente que la optimización (para la mayoría de los casos de uso) para la interpolación perezosa es que juega muy bien con los agregadores de registros como Sentry.

Considere un mensaje de registro 'usuario conectado'. Si interpola al usuario en la cadena de formato, tiene tantos mensajes de registro distintos como usuarios. Si usa una interpolación perezosa como esta, el agregador de registros puede interpretarlo más razonablemente como el mismo mensaje de registro con un montón de instancias diferentes.

Tristan Crockett
fuente