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?

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.


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 .


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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.