การบันทึก Python ไม่แสดงผลอะไรเลย


97

ในสคริปต์ python ฉันกำลังเขียนฉันกำลังพยายามบันทึกเหตุการณ์โดยใช้โมดูลการบันทึก ฉันมีรหัสต่อไปนี้เพื่อกำหนดค่าคนตัดไม้ของฉัน:

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)

เมื่อฉันพยายามเรียกใช้logging.debug("Some string")ฉันไม่ได้รับเอาต์พุตไปยังคอนโซลแม้ว่าหน้านี้ในเอกสารจะบอกว่าlogging.debugควรมีข้อความ root logger ออกมา เหตุใดโปรแกรมของฉันจึงไม่แสดงผลอะไรเลยและฉันจะแก้ไขได้อย่างไร

คำตอบ:


103

ระดับการบันทึกเริ่มต้นคือคำเตือน เนื่องจากคุณไม่ได้เปลี่ยนระดับระดับของ root logger จึงยังคงเตือนอยู่ นั่นหมายความว่าจะไม่สนใจการบันทึกใด ๆ ที่มีระดับต่ำกว่าคำเตือน

สิ่งนี้อธิบายไว้ในบทช่วยสอน :

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

บรรทัด "ข้อมูล" ไม่พิมพ์อะไรเลยเนื่องจากระดับสูงกว่าข้อมูล

หากต้องการเปลี่ยนระดับเพียงแค่ตั้งค่าใน root logger:

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

กล่าวอีกนัยหนึ่งก็ไม่เพียงพอที่จะกำหนดตัวจัดการที่มีระดับ = ดีบักระดับการบันทึกจริงต้องเป็นดีบักด้วยเพื่อให้ส่งออกอะไรก็ได้


7
เอกสารระบุว่าระดับเริ่มต้นคือ NOTSET ซึ่งเป็นระดับ 0 ซึ่งควรส่งออกทุกอย่าง ... เหตุใดจึงไม่เป็นความจริง
เบ็น

@ เบ็นไหนเอ่ย? สิ่งที่ฉันเห็นคือ "ระดับเริ่มต้นคือคำเตือนซึ่งหมายความว่าจะมีการติดตามเฉพาะเหตุการณ์ในระดับนี้ขึ้นไปเว้นแต่จะมีการกำหนดค่าแพ็กเกจการบันทึกให้ทำอย่างอื่น"
Omri Barel


1
@ เบ็นตามเอกสารผู้ตัดไม้จะถูกสำรวจเพื่อค้นหาพาเรนต์แรกที่มีlevel != NOTSETหรือรูท (หากไม่พบ) รากมีWARNINGระดับตามค่าเริ่มต้น สิ่งนี้เขียนไว้ในส่วนที่คุณเชื่อมโยงกับ ( Logger.setLevel)
Omri Barel

6
โปรดทราบว่าหลังจากนำเข้าloggingคุณต้องโทรlogging.basicConfig()อย่างน้อยหนึ่งครั้ง มิฉะนั้นคุณอาจแปลกใจไม่น้อยที่คนตัดไม้เด็กจะไม่พิมพ์อะไรเลย ฟังก์ชันการบันทึกบน root logger เรียกว่าขี้เกียจ
Hubert Grzeskowiak

74

หลายปีต่อมาดูเหมือนว่าจะยังคงมีปัญหาในการใช้งานกับ Python logger นี่คือคำอธิบายบางส่วนพร้อมตัวอย่าง:

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)

สาเหตุทั่วไปของความสับสนมาจาก root logger ที่เริ่มต้นไม่ดี พิจารณาสิ่งนี้:

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

เอาท์พุต:

woot
WARNING:myapp:woot

ทั้งนี้ขึ้นอยู่กับสภาพแวดล้อมรันไทม์ของคุณและเข้าสู่ระบบระดับสายการบันทึกครั้งแรก (ก่อนที่จะกำหนดค่าพื้นฐาน) อาจจะไม่แสดงขึ้นที่ใดก็ได้


การบันทึกของฉันไม่ทำงานเนื่องจากไม่มีไฟล์เอาต์พุต คุณเห็นสิ่งที่ฉันทำผิดอย่างชัดเจนหรือไม่? logging.basicConfig( filename='logging.txt', level=logging.DEBUG) logger = logging.getLogger() logger.info('Test B') logging.info('Test A')
Rylan Schaeffer

ไฟล์บันทึกไม่ได้ถูกสร้างขึ้น
Rylan Schaeffer

ผมสังเกตเห็นเมื่อฉันวางจุดพักหลังจากระดับที่ถูกกำหนดเป็นคำเตือนแม้ว่าฉันระบุระดับเป็นlogger = logging.getLogger() DEBUGรู้ไหมว่าฉันทำอะไรผิด?
Rylan Schaeffer

สวัสดี @RylanSchaeffer คุณอาจต้องการสร้างคำถามใหม่และให้รายละเอียดเพิ่มเติม นอกจากนี้ยังจะให้โอกาสคนอื่นช่วยคุณ
Hubert Grzeskowiak

ฉันทำ. บ่อยครั้งการถามความคิดเห็นเป็นวิธีที่เร็วกว่าในการหาคำตอบเพราะมีผู้รู้อย่างน้อยหนึ่งคนจะเห็นคำถามของฉัน
Rylan Schaeffer

27

สำหรับใครก็ตามที่ต้องการคำตอบง่ายๆเพียงตั้งค่าระดับที่คุณต้องการให้แสดง ที่ด้านบนของสคริปต์ทั้งหมดของฉันฉันใส่:

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

จากนั้นเพื่อแสดงสิ่งใด ๆ ที่หรือสูงกว่าระดับนั้น:

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

มันเป็นชุดที่มีลำดับชั้นของห้าระดับเพื่อที่บันทึกจะแสดงในระดับที่คุณตั้งค่าไว้หรือสูงกว่า ดังนั้นหากคุณต้องการแสดงข้อผิดพลาดคุณสามารถlogging.error("The plumbus is broken")ใช้ได้

ระดับในลำดับที่เพิ่มขึ้นของความรุนแรงมีDEBUG, INFO, WARNING, และERROR ค่าเริ่มต้นคือCRITICALWARNING

นี่เป็นบทความที่ดีที่มีข้อมูลนี้แสดงได้ดีกว่าคำตอบของฉัน:
https://www.digitalocean.com/community/tutorials/how-to-use-logging-in-python-3


14

อาจจะลองดูไหม ดูเหมือนว่าปัญหาจะได้รับการแก้ไขหลังจากถอดตัวจัดการทั้งหมดในเคสของฉัน

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

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

SyntaxError: invalid syntax
Eric

2
เหตุใดจึงจำเป็น ตัวจัดการใดที่มาพร้อมกับเครื่องตัดไม้ python และเหตุใดจึงเริ่มต้นด้วย? หรืออาจเป็นคำถามคือทำไม basicConfig ไม่แทนที่ / แทนที่พวกเขา?
jrh
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.