मैं लॉगिंग मॉड्यूल को एक मजेदार तरीके से व्यवहार कर रहा हूं। क्या मैं कुछ भूल रहा हूँ ?अजीब: लॉगर केवल अपवादों के लिए पहले हैंडलर के फॉर्मेटर का उपयोग करता है
मैं दो हैंडलर रखने की सामान्य बात कर रहा हूं: केवल स्ट्रीमिंग के लिए स्ट्रीमहैंडर और कंसोल के लिए उच्च, और एक फाइलहैंडलर जो सभी डीईबीयूजी जानकारी को भी संभाल लेगा।
यह ठीक काम करता है जब तक कि मैंने निष्पादन के लिए एक अलग प्रारूप नहीं तय किया। मैं फ़ाइल में एक पूर्ण stacktrace चाहता था, लेकिन कंसोल पर बस अपवाद प्रकार और मूल्य। चूंकि हैंडलर के पास एक सेटफॉर्मेटर फ़ंक्शन है, और चूंकि लॉगिंग के उप-वर्ग को लिखना आसान लगता है। फ़ॉर्मेटर, मैंने सोचा कि यह काम करेगा।
कंसोल हैंडलर और फ़ाइल हैंडलर दोनों का अपना फॉर्मेटर है। कोड में प्रिंट स्टेटमेंट इसे साबित करता है। हालांकि, logger.exception के लिए कॉल केवल पहले हैंडलर के प्रारूप अपवाद का उपयोग करेगा => फ़ाइल में अपवाद लॉग इन होना चाहिए जिसमें प्रारूप में होना चाहिए। Logger.addHandler लाइनों का क्रम बदलें और फिर यह फ़ाइल हैंडलर का प्रारूप अपवाद है जिसका हर जगह प्रयोग किया जाता है।
import logging
import sys
class ConsoleFormatter(logging.Formatter):
def formatException(self, exc_info):
# Ugly but obvious way to see who's talking.
return "CONSOLE EXCEPTION %s: %s" % exc_info[:2]
def setup(path):
logger = logging.getLogger()
#
file_handler = logging.FileHandler(path, mode='w')
if __debug__:
file_handler.setLevel(logging.DEBUG)
else:
file_handler.setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s %(levelname)-8s "
"%(name)-16s %(message)s "
"[%(filename)[email protected]%(lineno)d in %(funcName)s]")
file_handler.setFormatter(formatter)
#
console_handler = logging.StreamHandler(sys.stderr)
console_handler.setLevel(logging.INFO)
console_formatter = ConsoleFormatter("%(levelname)-8s - %(message)s")
console_handler.setFormatter(console_formatter)
# >>> FUN HAPPENS HERE <<<
# Only the formatter of the first handler is used ! Both on the console
# and in the file. Change the order of these two lines to see.
logger.addHandler(console_handler)
logger.addHandler(file_handler)
#
# Proof that the two handlers have different formatters:
print logger.handlers
print file_handler.formatter.formatException
print console_formatter.formatException
#
logger.setLevel(logging.DEBUG)
logger.info("Logger ready.")
setup('test.log')
logger = logging.getLogger()
logger.debug("Only visible in the file.")
try:
1/0
except ZeroDivisionError:
logger.exception("boom")
क्या चल रहा है?
संपादित करें: मैं रास्ते में पायथन 2.6 का उपयोग कर रहा हूं। संपादित करें: "console_formatter" चर नाम के बारे में कोड में टाइपो सही किया गया।
Traceback (most recent call last):
File "logger.py", line 42, in <module>
setup('test.log')
File "logger.py", line 37, in setup
print console_formatter.formatException
NameError: global name 'console_formatter' is not defined
शायद मुद्दे का स्रोत है कि:
बढ़िया! लॉगिंग subclassing द्वारा। फॉर्मेटर मैं प्रारूप() को ओवरराइड कर सकता था। यह ओवरडिन विधि सुपरक्लास 'प्रारूप() को कॉल करने से पहले किसी को भी record.exc_text सेट नहीं करती है और इसके बाद इसके पिछले मान को पुनर्स्थापित करती है। इस तरह, मैं किसी भी कोड को डुप्लिकेट किए बिना अपवाद टेक्स्ट की कैशिंग अक्षम करता हूं। फिर, मैं अपने दो हैंडलरों के लिए बेस कैस के रूप में इस कैशलेसफॉर्मेटर का उपयोग करता हूं और यह \ o /। धन्यवाद ! – Niriel