जवाबों:
ट्रेस जानकारी के साथ वर्तमान अपवाद को लॉग करने के logging.exception
लिए except:
हैंडलर / ब्लॉक के भीतर से उपयोग करें , संदेश के साथ प्रस्तुत किया गया।
import logging
LOG_FILENAME = '/tmp/logging_example.out'
logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG)
logging.debug('This message should go to the log file')
try:
run_my_stuff()
except:
logging.exception('Got exception on main handler')
raise
अब लॉग फाइल देख रहे हैं /tmp/logging_example.out
:
DEBUG:root:This message should go to the log file
ERROR:root:Got exception on main handler
Traceback (most recent call last):
File "/tmp/teste.py", line 9, in <module>
run_my_stuff()
NameError: name 'run_my_stuff' is not defined
logger = logging.getLogger('yourlogger')
लिए लिखना logger.exception('...')
होगा ...
उपयोग के exc_info
विकल्प बेहतर हो सकते हैं, चेतावनी या त्रुटि शीर्षक रहता है:
try:
# coode in here
except Exception as e:
logging.error(e, exc_info=True)
exc_info=
कर्ग को क्या कहा जाता है; धन्यवाद!
logging.exception
मेरा काम हाल ही में हमारे आवेदन से सभी ट्रेसबैक / अपवाद लॉगिंग के साथ मुझे सौंपा। मैंने ऐसी कई तकनीकें आजमाईं जो दूसरों ने ऑनलाइन पोस्ट की थीं जैसे कि ऊपर एक लेकिन एक अलग दृष्टिकोण पर बस गया। ओवरराइडिंग traceback.print_exception
।
मुझे http://www.bbarrows.com/ पर लिखना है । यह पढ़ना बहुत आसान होगा, लेकिन इल इसमें भी पेस्ट करें।
जब सभी अपवादों को लॉग करने के साथ काम किया जाता है, तो हमारे सॉफ्टवेयर का जंगली में सामना हो सकता है मैंने अपने अजगर अपवाद ट्रेसबैक को लॉग करने के लिए कई विभिन्न तकनीकों की कोशिश की। पहले मैंने सोचा था कि लॉगऑन कोड डालने के लिए अजगर सिस्टम अपवाद हुक, sys.excepthook सही जगह होगा। मैं कुछ इसी तरह की कोशिश कर रहा था:
import traceback
import StringIO
import logging
import os, sys
def my_excepthook(excType, excValue, traceback, logger=logger):
logger.error("Logging an uncaught exception",
exc_info=(excType, excValue, traceback))
sys.excepthook = my_excepthook
इसने मुख्य सूत्र के लिए काम किया लेकिन मुझे जल्द ही पता चला कि मेरी sys.excepthook मेरी प्रक्रिया शुरू होने वाले किसी भी नए सूत्र में मौजूद नहीं होगी। यह एक बहुत बड़ा मुद्दा है क्योंकि इस परियोजना में ज्यादातर सब कुछ थ्रेड में होता है।
गुग्लिंग और बहुत सारे दस्तावेज़ पढ़ने के बाद मुझे जो सबसे उपयोगी जानकारी मिली वह पायथन इश्यू ट्रैकर की थी।
थ्रेड पर पहला पोस्ट sys.excepthook
थ्रेड्स के पार नहीं जारी ( उदाहरण के रूप में नीचे दिखाया गया है) का एक कार्यशील उदाहरण दिखाता है । स्पष्ट रूप से यह अपेक्षित व्यवहार है।
import sys, threading
def log_exception(*args):
print 'got exception %s' % (args,)
sys.excepthook = log_exception
def foo():
a = 1 / 0
threading.Thread(target=foo).start()
इस पायथन इश्यू थ्रेड पर संदेश वास्तव में 2 सुझाए गए हैक्स में परिणाम करते हैं। Thread
ब्लॉक को छोड़कर हमारी अपनी कोशिश में रनक्लैट को या तो सबक्लास में लपेटें और अपवादों को पकड़ने या लॉग इन करने के लिए या threading.Thread.run
ब्लॉक को छोड़कर अपनी खुद की कोशिश में लॉग इन करें और अपवादों को लॉग इन करें।
सबक्लासिंग की पहली विधि Thread
मुझे अपने कोड में कम सुरुचिपूर्ण लगती है क्योंकि आपको अपनी कस्टम Thread
क्लास EVERYWHERE का आयात और उपयोग करना होगा जिसे आप लॉगिंग थ्रेड करना चाहते थे। यह एक परेशानी का कारण बना क्योंकि मुझे अपना पूरा कोड आधार खोजना पड़ा और Threads
इस रिवाज के साथ सभी सामान्य को बदलना पड़ा Thread
। हालांकि, यह स्पष्ट था कि यह क्या Thread
कर रहा था और किसी के लिए निदान करने और डिबग करना आसान होगा यदि कस्टम लॉग कोड के साथ कुछ गलत हुआ। एक छोटा लॉगिंग थ्रेड इस तरह दिख सकता है:
class TracebackLoggingThread(threading.Thread):
def run(self):
try:
super(TracebackLoggingThread, self).run()
except (KeyboardInterrupt, SystemExit):
raise
except Exception, e:
logger = logging.getLogger('')
logger.exception("Logging an uncaught exception")
मंकी पैचिंग threading.Thread.run
का दूसरा तरीका अच्छा है क्योंकि मैं इसे एक बार ही सही पर चला सकता हूं __main__
और सभी अपवादों में अपना लॉगिंग कोड लिख सकता हूं। बंदर पैचिंग डिबग करने के लिए कष्टप्रद हो सकता है, क्योंकि यह किसी चीज़ की अपेक्षित कार्यक्षमता को बदल देता है। पायथन इश्यू ट्रैकर से सुझाया गया पैच था:
def installThreadExcepthook():
"""
Workaround for sys.excepthook thread bug
From
http://spyced.blogspot.com/2007/06/workaround-for-sysexcepthook-bug.html
(https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1230540&group_id=5470).
Call once from __main__ before creating any threads.
If using psyco, call psyco.cannotcompile(threading.Thread.run)
since this replaces a new-style class method.
"""
init_old = threading.Thread.__init__
def init(self, *args, **kwargs):
init_old(self, *args, **kwargs)
run_old = self.run
def run_with_except_hook(*args, **kw):
try:
run_old(*args, **kw)
except (KeyboardInterrupt, SystemExit):
raise
except:
sys.excepthook(*sys.exc_info())
self.run = run_with_except_hook
threading.Thread.__init__ = init
यह तब तक नहीं था जब तक कि मैंने अपने अपवाद लॉगिंग का परीक्षण शुरू नहीं किया था मुझे एहसास हुआ कि मैं इसके बारे में गलत था।
परीक्षण करने के लिए मैंने एक रखा था
raise Exception("Test")
मेरे कोड में कहीं। हालाँकि, इस पद्धति को लपेटने वाली विधि को ब्लॉक करने के अलावा ट्रेसबैक को प्रिंट करने और अपवाद को निगलने के अलावा एक कोशिश थी। यह बहुत निराशाजनक था क्योंकि मैंने ट्रेसबैक को एसटीडीयूएस के लिए मुद्रित करके देखा, लेकिन लॉग नहीं किया जा रहा था। यह तब मैंने तय किया था कि ट्रेसबैक को लॉग करने का एक बहुत आसान तरीका सिर्फ बंदर का तरीका था जो कि सभी अजगर कोड ट्रेसबैक को प्रिंट करने के लिए उपयोग करता है, ट्रेसबैक।प्रिंट_एक्ससेप्शन। मैं निम्नलिखित के समान कुछ के साथ समाप्त हुआ:
def add_custom_print_exception():
old_print_exception = traceback.print_exception
def custom_print_exception(etype, value, tb, limit=None, file=None):
tb_output = StringIO.StringIO()
traceback.print_tb(tb, limit, tb_output)
logger = logging.getLogger('customLogger')
logger.error(tb_output.getvalue())
tb_output.close()
old_print_exception(etype, value, tb, limit=None, file=None)
traceback.print_exception = custom_print_exception
यह कोड एक स्ट्रिंग बफ़र के लिए ट्रेसबैक लिखता है और लॉगिंग ईआरआरओआर में प्रवेश करता है। मेरे पास एक कस्टम लॉगिंग हैंडलर है जो 'customLogger' लॉगर सेट करता है जो ERROR लेवल लॉग लेता है और उन्हें विश्लेषण के लिए घर भेजता है।
add_custom_print_exception
आप जिस साइट से जुड़े हुए हैं, उस पर प्रतीत नहीं होता है और इसके बजाय वहाँ कुछ अलग अंतिम कोड है। आप किसको बेहतर / अधिक अंतिम कहेंगे और क्यों? धन्यवाद!
logger.error(traceback.format_tb())
(या format_exc) कॉल कर सकते हैं (यदि आप अपवाद जानकारी भी चाहते हैं)।
आप मुख्य थ्रेड पर सभी अप्रकाशित अपवादों को एक हैंडलर को सौंपकर लॉग इन कर सकते हैं sys.excepthook
, शायद exc_info
पायथन के लॉगिंग मानकों के पैरामीटर का उपयोग करते हुए :
import sys
import logging
logging.basicConfig(filename='/tmp/foobar.log')
def exception_hook(exc_type, exc_value, exc_traceback):
logging.error(
"Uncaught exception",
exc_info=(exc_type, exc_value, exc_traceback)
)
sys.excepthook = exception_hook
raise Exception('Boom')
यदि आपका प्रोग्राम थ्रेड्स का उपयोग करता है, हालाँकि, तो ध्यान दें कि उपयोग किए गए थ्रेड ट्रिगर नहींthreading.Thread
होंगे जब उनके अंदर एक अनकहा अपवाद उत्पन्न होता है, जैसा कि पायथन के इश्यू ट्रैकर पर अंक 1230540 में उल्लेख किया गया है । इस सीमा के आसपास काम करने के लिए कुछ हैक का सुझाव दिया गया है, जैसे बंदर-पैचिंग एक वैकल्पिक विधि के साथ ओवरराइट करने के लिए जो मूल को ब्लॉक में लपेटता है और ब्लॉक के अंदर से कॉल करता है। वैकल्पिक रूप से, आप बस मैन्युअल रूप में अपने धागे से प्रत्येक के लिए प्रवेश बिंदु लपेट सकता है / खुद।sys.excepthook
Thread.__init__
self.run
run
try
sys.excepthook
except
try
except
अनकैप्ड अपवाद संदेश STDERR पर जाते हैं, इसलिए Python में अपनी लॉगिंग को लागू करने के बजाय आप STDERR को अपनी पायथन लिपि को चलाने के लिए जो भी शेल का उपयोग कर रहे हैं उसे एक फ़ाइल में भेज सकते हैं। बैश स्क्रिप्ट में, आप इसे आउटपुट रीडायरेक्शन के साथ कर सकते हैं, जैसा कि BASH गाइड में वर्णित है ।
टर्मिनल के लिए अन्य आउटपुट फाइल करने के लिए त्रुटियों को जोड़ें:
./test.py 2>> mylog.log
Interleaved STDOUT और STDERR आउटपुट के साथ ओवरराइट फ़ाइल:
./test.py &> mylog.log
मैं क्या देख रहा था:
import sys
import traceback
exc_type, exc_value, exc_traceback = sys.exc_info()
traceback_in_var = traceback.format_tb(exc_traceback)
देख:
आप किसी भी स्तर पर (एक प्रकार का जानवर, जानकारी, ...) का उपयोग करके ट्रेसबैक प्राप्त कर सकते हैं। ध्यान दें कि उपयोग करते हुए logging.exception
, स्तर ERROR है।
# test_app.py
import sys
import logging
logging.basicConfig(level="DEBUG")
def do_something():
raise ValueError(":(")
try:
do_something()
except Exception:
logging.debug("Something went wrong", exc_info=sys.exc_info())
DEBUG:root:Something went wrong
Traceback (most recent call last):
File "test_app.py", line 10, in <module>
do_something()
File "test_app.py", line 7, in do_something
raise ValueError(":(")
ValueError: :(
संपादित करें:
यह भी काम करता है (अजगर 3.6 का उपयोग करके)
logging.debug("Something went wrong", exc_info=True)
यहाँ एक संस्करण है जो sys.excepthook का उपयोग करता है
import traceback
import sys
logger = logging.getLogger()
def handle_excepthook(type, message, stack):
logger.error(f'An unhandled exception occured: {message}. Traceback: {traceback.format_tb(stack)}')
sys.excepthook = handle_excepthook
{traceback.format_exc()}
बजाय का उपयोग कैसे करें {traceback.format_tb(stack)}
?
शायद उतना स्टाइलिश नहीं, लेकिन आसान:
#!/bin/bash
log="/var/log/yourlog"
/path/to/your/script.py 2>&1 | (while read; do echo "$REPLY" >> $log; done)
अजगर 2.6 दस्तावेज से लिया गया एक सरल उदाहरण है :
import logging
LOG_FILENAME = '/tmp/logging_example.out'
logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG,)
logging.debug('This message should go to the log file')