Mensagem PyLint: interpolação de formato de log

161

Para o seguinte código:

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

pylint produz o seguinte aviso:

interpolação de formato de log (W1202):

Use a formatação% nas funções de log e passe os parâmetros% como argumentos Utilizados quando uma instrução de log possui um formulário de chamada de “log. (Format_string.format (format_args ...))”. Essas chamadas devem usar% de formatação, mas deixar a interpolação para a função de log passando os parâmetros como argumentos.

Sei que posso desativar esse aviso, mas gostaria de entendê-lo. Eu assumi que usar format()é a maneira preferida de imprimir instruções no Python 3. Por que isso não é verdade para instruções do logger?

pfnuesel
fonte

Respostas:

203

Isso não é verdadeiro para a declaração do criador de logs, porque conta com o formato "%" anterior, como string, para fornecer interpolação lenta dessa string usando argumentos extras fornecidos para a chamada do criador de logs. Por exemplo, em vez de fazer:

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

você deveria fazer

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

portanto, a cadeia só será interpolada se a mensagem for realmente emitida.

Você não pode se beneficiar dessa funcionalidade ao usar .format().


De acordo com a seção Otimização dos loggingdocumentos:

A formatação dos argumentos da mensagem é adiada até que não possa ser evitada. No entanto, calcular os argumentos passados ​​para o método de registro também pode ser caro, e você pode evitar fazê-lo se o criador de logs simplesmente jogar fora seu evento.

sthenault
fonte
4
@pfnuesel, .format () é expandido antes da chamada para logger.error, enquanto "interpolação lenta" significa que a expansão é feita apenas se necessário (por exemplo, a mensagem é realmente exibida em algum lugar)
sthenault
10
Existe uma boa referência para essa avaliação preguiçosa ser preferida e fazer a diferença? Eu não poderia encontrar um em PEP282 ou a biblioteca logging
culix
25
Mas isso significa apenas que teremos problemas de manutenção com nosso código mais tarde? Mais tarde, seremos "recomendados" pela pylint para mudar para o .format()estilo em algum momento porque loggingfoi atualizado? Pergunto porque estou mais interessado em manutenção do que em desempenho de velocidade de ponta, pelo menos na maioria das tarefas.
Mike Williamson
3
@ MikeWilliamson: Eu acho que esta mensagem é um aviso, pois existem possíveis efeitos colaterais, mas você pode ignorá-la com segurança.
Saihtamtellim
5
Embora grande parte da motivação por trás do aviso esteja relacionada ao desempenho (ou seja, se uma declaração de log não for emitida, o custo de interpolação é economizado), é importante notar que em muitas aplicações (provavelmente na maioria) o custo de desempenho é insignificante. Veja: github.com/PyCQA/pylint/issues/2395 e github.com/PyCQA/pylint/issues/2354
Adam Parkin
23

Talvez desta vez as diferenças possam ajudá-lo.

A descrição a seguir não é a resposta para sua pergunta, mas pode ajudar as pessoas.

Para pylint 2.4: Existem 3 opções para login estilo no .pylintrcarquivo: old, new,fstr

fstropção adicionada em 2.4 e removida em 2.5

Descrição do .pylintrcarquivo (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 old ( 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 : você não pode usar, .format()mesmo se você selecionar a newopção.

O pylint ainda dá o mesmo aviso 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}")

Pessoalmente, prefiro a opção fstr por causa do PEP-0498 .

mustafagok
fonte
2
você pode adicionar "python.linting.pylintArgs": ["--logging-format-style=old"]ao arquivo vscode / settings.json. docs
mustafagok
2
no pylint 2.3.1: a optparse.OptionValueError: option logging-format-style: invalid value: 'fstr', should be in ['old', 'new']atualização para o pylint mais recente (2.4.4) corrigiu isso.
Florian Castellane
Estou tendo o seguinte erro: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
3

Na minha experiência, uma razão mais convincente do que a otimização (na maioria dos casos de uso) para a interpolação lenta é que ela funciona muito bem com agregadores de logs como o Sentry.

Considere uma mensagem de log 'usuário logado'. Se você interpolar o usuário na cadeia de formatação, você terá tantas mensagens de log distintas quanto os usuários. Se você usar uma interpolação lenta como essa, o agregador de log poderá interpretar isso mais razoavelmente como a mesma mensagem de log com várias instâncias diferentes.

Tristan Crockett
fonte