Python günlük kaydı hiçbir şey vermiyor


97

Bir python betiğinde yazdığım olayları günlüğe kaydetme modülünü kullanarak günlüğe kaydetmeye çalışıyorum. Kaydedicimi yapılandırmak için aşağıdaki koda sahibim:

ERROR_FORMAT = "%(levelname)s at %(asctime)s in %(funcName)s in %(filename) at line %(lineno)d: %(message)s"
DEBUG_FORMAT = "%(lineno)d in %(filename)s at %(asctime)s: %(message)s"
LOG_CONFIG = {'version':1,
              'formatters':{'error':{'format':ERROR_FORMAT},
                            'debug':{'format':DEBUG_FORMAT}},
              'handlers':{'console':{'class':'logging.StreamHandler',
                                     'formatter':'debug',
                                     'level':logging.DEBUG},
                          'file':{'class':'logging.FileHandler',
                                  'filename':'/usr/local/logs/DatabaseUpdate.log',
                                  'formatter':'error',
                                  'level':logging.ERROR}},
              'root':{'handlers':('console', 'file')}}
logging.config.dictConfig(LOG_CONFIG)

Çalıştırmayı denediğimde , dokümanlardaki bu sayfada mesajın kök günlükçünün çıktısını alması gerektiğini söylese logging.debug("Some string")de konsola hiçbir çıktı alamıyorum . Programım neden hiçbir çıktı vermiyor ve bunu nasıl düzeltebilirim?logging.debug

Yanıtlar:


103

Varsayılan günlük kaydı seviyesi uyarıdır. Seviyeyi değiştirmediğiniz için, kök kaydedicinin seviyesi hala uyarılıyor. Bu, hata ayıklama günlükleri de dahil olmak üzere uyarıdan daha düşük bir seviyeye sahip günlükleri yok sayacağı anlamına gelir.

Bu, eğiticide açıklanmıştır :

import logging
logging.warning('Watch out!') # will print a message to the console
logging.info('I told you so') # will not print anything

Seviye, bilgiden daha yüksek olduğu için 'bilgi' satırı hiçbir şey yazdırmaz.

Seviyeyi değiştirmek için kök kaydedicide ayarlamanız yeterlidir:

'root':{'handlers':('console', 'file'), 'level':'DEBUG'}

Başka bir deyişle, level = DEBUG ile bir işleyiciyi tanımlamak yeterli değildir, herhangi bir çıktı vermesini sağlamak için gerçek loglama seviyesi de DEBUG olmalıdır.


7
Dokümantasyon, varsayılan seviyesinin NOTSET olduğunu söylüyor ki bu da 0 seviyesidir ve her şeyi çıkarmalıdır ... Bu neden doğru değil?
Ben

@Ben bunu nerede söylüyor? Tek görebildiğim, "Varsayılan düzey UYARI'dır, bu, günlük paketi başka türlü yapacak şekilde yapılandırılmadıkça, yalnızca bu düzey ve üzerindeki olayların izleneceği anlamına gelir."
Omri Barel


1
@Ben Dokümanlara göre kaydediciler ilk ebeveyni level != NOTSETveya kökü bulmak için geçilir (eğer hiçbiri bulunamazsa). Kök WARNINGvarsayılan olarak seviyeye sahiptir . Bu, ( Logger.setLevel) ile bağlantı kurduğunuz bölümde yazılmıştır .
Omri Barel

6
İçe aktardıktan sonra en az bir kez loggingaramanız gerektiğini unutmayın logging.basicConfig(). Aksi takdirde, çocuk kaydedicilerin hiçbir şey yazdırmamasına çok şaşırabilirsiniz. Kök kaydedicideki günlük kaydı işlevleri, onu tembel olarak çağırır.
Hubert Grzeskowiak

74

Yıllar sonra Python kaydedici ile hala bir kullanılabilirlik sorunu var gibi görünüyor. İşte örneklerle bazı açıklamalar:

import logging
# This sets the root logger to write to stdout (your console).
# Your script/app needs to call this somewhere at least once.
logging.basicConfig()

# By default the root logger is set to WARNING and all loggers you define
# inherit that value. Here we set the root logger to NOTSET. This logging
# level is automatically inherited by all existing and new sub-loggers
# that do not set a less verbose level.
logging.root.setLevel(logging.NOTSET)

# The following line sets the root logger level as well.
# It's equivalent to both previous statements combined:
logging.basicConfig(level=logging.NOTSET)


# You can either share the `logger` object between all your files or the
# name handle (here `my-app`) and call `logging.getLogger` with it.
# The result is the same.
handle = "my-app"
logger1 = logging.getLogger(handle)
logger2 = logging.getLogger(handle)
# logger1 and logger2 point to the same object:
# (logger1 is logger2) == True


# Convenient methods in order of verbosity from highest to lowest
logger.debug("this will get printed")
logger.info("this will get printed")
logger.warning("this will get printed")
logger.error("this will get printed")
logger.critical("this will get printed")


# In large applications where you would like more control over the logging,
# create sub-loggers from your main application logger.
component_logger = logger.getChild("component-a")
component_logger.info("this will get printed with the prefix `my-app.component-a`")

# If you wish to control the logging levels, you can set the level anywhere 
# in the hierarchy:
#
# - root
#   - my-app
#     - component-a
#

# Example for development:
logger.setLevel(logging.DEBUG)

# If that prints too much, enable debug printing only for your component:
component_logger.setLevel(logging.DEBUG)


# For production you rather want:
logger.setLevel(logging.WARNING)

Yaygın bir kafa karışıklığı kaynağı, kötü başlatılmış bir kök kaydediciden gelir. Bunu düşün:

import logging
log = logging.getLogger("myapp")
log.warning("woot")
logging.basicConfig()
log.warning("woot")

Çıktı:

woot
WARNING:myapp:woot

Çalışma zamanı ortamınıza ve günlük seviyelerine bağlı olarak , ilk günlük satırı (temel yapılandırmadan önce) hiçbir yerde görünmeyebilir .


Günlük kaydım hiçbir çıktı dosyası oluşturmadığı için çalışmıyor. Yaptığım açıkça yanlış olan bir şey görüyor musun? logging.basicConfig( filename='logging.txt', level=logging.DEBUG) logger = logging.getLogger() logger.info('Test B') logging.info('Test A')
Rylan Schaeffer

Günlük dosyası bile oluşturulmadı
Rylan Schaeffer

Sonrasında bir kırılma noktası düşürdüğümde logger = logging.getLogger(), seviyeyi olarak belirlememe rağmen seviyenin UYARI olarak ayarlandığını fark ettim DEBUG. Neyi yanlış yaptığımı biliyor musun?
Rylan Schaeffer

Merhaba @RylanSchaeffer, yeni bir soru oluşturmak ve biraz daha ayrıntı vermek isteyebilirsiniz. Bu aynı zamanda başkalarına da size yardım etme şansı verecektir.
Hubert Grzeskowiak

Yaptım. Sıklıkla yorum sormak, yanıt bulmanın daha hızlı bir yoludur çünkü en az bir bilgili kişi sorumu görecek
Rylan Schaeffer

27

Burada süper basit bir cevap isteyen herkes için: sadece görüntülenmesini istediğiniz seviyeyi ayarlayın. Az önce koyduğum tüm komut dosyalarımın başına:

import logging
logging.basicConfig(level = logging.INFO)

Daha sonra bu seviyede veya üzerindeki herhangi bir şeyi görüntülemek için:

logging.info("Hi you just set your fleeb to level plumbus")

Günlüklerin belirlediğiniz seviyede veya daha yüksek bir seviyede görüntülenebilmesi için beş seviyeden oluşan hiyerarşik bir kümedir . Yani bir hatayı görüntülemek istiyorsanız kullanabilirsiniz logging.error("The plumbus is broken").

Şiddeti artan sırada seviyeleri vardır DEBUG, INFO, WARNING, ERROR, ve CRITICAL. Varsayılan ayar WARNING.

Bu, cevabımdan daha iyi ifade edilen bu bilgileri içeren iyi bir makale:
https://www.digitalocean.com/community/tutorials/how-to-use-logging-in-python-3


14

Belki bunu dene? Benim durumumdaki tüm işleyicileri kaldırdıktan sonra sorun çözülmüş görünüyor.

for handler in logging.root.handlers[:]:
    logging.root.removeHandler(handler)

logging.basicConfig(filename='output.log', level=logging.INFO)

SyntaxError: invalid syntax
Eric

2
Bu neden gerekli? Python kaydediciyle hangi işleyiciler stokta gelir ve neden başlamak için oradalar? Ya da belki soru şu: basicConfig neden onları geçersiz kılmıyor / değiştirmiyor?
jrh
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.