Komunikat PyLint: interpolacja formatu logowania

161

Dla następującego kodu:

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

pylint generuje następujące ostrzeżenie:

interpolacja formatu logowania (W1202):

Użyj formatowania% w funkcjach rejestrowania i przekaż parametry% jako argumenty Używane, gdy instrukcja logowania ma postać wywołania „logging. (Format_string.format (format_args ...))”. Takie wywołania powinny zamiast tego używać formatowania%, ale pozostawić interpolację funkcji rejestrowania, przekazując parametry jako argumenty.

Wiem, że mogę wyłączyć to ostrzeżenie, ale chciałbym je zrozumieć. Założyłem, że używanie format()jest preferowanym sposobem drukowania instrukcji w Pythonie 3. Dlaczego nie jest to prawdą w przypadku instrukcji rejestrujących?

pfnuesel
źródło

Odpowiedzi:

203

Nie jest to prawdą w przypadku instrukcji rejestrującej, ponieważ opiera się ona na poprzednim formacie „%”, takim jak łańcuch, w celu zapewnienia leniwej interpolacji tego ciągu przy użyciu dodatkowych argumentów przekazanych do wywołania rejestratora. Na przykład zamiast robić:

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

powinieneś zrobić

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

więc łańcuch będzie interpolowany tylko wtedy, gdy wiadomość zostanie faktycznie wyemitowana.

Nie możesz korzystać z tej funkcji podczas korzystania z .format().


Zgodnie z sekcją Optymalizacja w loggingdokumentacji:

Formatowanie argumentów wiadomości jest odroczone, dopóki nie będzie można tego uniknąć. Jednak obliczanie argumentów przekazanych do metody rejestrowania może być również kosztowne i możesz chcieć tego uniknąć, jeśli rejestrator po prostu wyrzuci twoje zdarzenie.

sthenault
źródło
4
@pfnuesel, .format () jest rozwijane przed wywołaniem logger.error, podczas gdy "leniwa interpolacja" oznacza, że ​​ekspansja jest wykonywana tylko w razie potrzeby (np. wiadomość jest faktycznie gdzieś wyświetlana)
sthenault
10
Czy istnieje dobre odniesienie do tego, że ta leniwa ocena jest preferowana i robi różnicę? Nie mogłem znaleźć takiego w PEP282 ani w bibliotece
logów
25
Ale czy to tylko oznacza, że ​​później będziemy mieli problemy z konserwacją naszego kodu? Czy później pylint „poleci” nam przejście do .format()stylu w którymś momencie, ponieważ loggingzostał ulepszony? Pytam, ponieważ bardziej interesuje mnie łatwość konserwacji niż niesamowita wydajność, przynajmniej w przypadku większości zadań.
Mike Williamson
3
@MikeWilliamson: Myślę, że ta wiadomość jest ostrzeżeniem, ponieważ istnieją możliwe skutki uboczne, ale możesz ją bezpiecznie zignorować.
saihtamtellim
5
Chociaż znaczna część motywacji stojącej za ostrzeżeniem jest związana z wydajnością (tj .: jeśli nie jest emitowany zapis dziennika, oszczędza się koszt interpolacji), warto zauważyć, że w wielu (prawdopodobnie większości) aplikacjach koszt wydajności jest znikomy. Zobacz: github.com/PyCQA/pylint/issues/2395 i github.com/PyCQA/pylint/issues/2354
Adam Parkin
23

Może tym razem różnice pomogą Ci .

Poniższy opis nie jest odpowiedzią na Twoje pytanie, ale może pomóc ludziom.

Dla pylint 2.4: Istnieją 3 opcje zalogowaniu styl w .pylintrcpliku: old, new,fstr

fstropcja dodana w 2.4 i usunięta w 2.5

Opis z .pylintrcpliku (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

dla starego ( logging-format-style=old):

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

dla nowego ( logging-format-style=new):

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

Uwaga : można nie używać .format()nawet po wybraniunew opcji.

pylint nadal daje to samo ostrzeżenie dla tego kodu:

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

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

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

Osobiście wolę opcję fstr ze względu na PEP-0498 .

mustafagok
źródło
2
możesz dodać "python.linting.pylintArgs": ["--logging-format-style=old"]do pliku vscode / settings.json. docs
mustafagok
2
w pylint 2.3.1: optparse.OptionValueError: option logging-format-style: invalid value: 'fstr', should be in ['old', 'new']aktualizacja do najnowszej wersji pylint (2.4.4) naprawiła ten problem.
Florian Castellane
Mam następujący błąd: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

Z mojego doświadczenia wynika, że ​​bardziej przekonującym powodem niż optymalizacja (w większości przypadków użycia) leniwej interpolacji jest to, że działa ona dobrze z agregatorami dzienników, takimi jak Sentry.

Rozważ komunikat dziennika „użytkownik zalogował się”. Jeśli interpolujesz użytkownika do ciągu formatu, masz tyle różnych komunikatów dziennika, ile jest użytkowników. Jeśli używasz tak leniwej interpolacji, agregator dziennika może rozsądniej zinterpretować to jako ten sam komunikat dziennika z wieloma różnymi wystąpieniami.

Tristan Crockett
źródło