python - मैं डीबग जानकारी के साथ एक पायथन त्रुटि कैसे लॉग करूं?




exception logging exception-handling (8)

मैं logging.error साथ लॉग फ़ाइल में पायथन अपवाद संदेश प्रिंट कर रहा हूं। logging.error :

import logging
try:
    1/0
except Exception as e:
    logging.error(e)  # ERROR:root:division by zero

क्या अपवाद और कोड जो इसे अपवाद स्ट्रिंग की तुलना में उत्पन्न करता है, के बारे में अधिक विस्तृत जानकारी मुद्रित करना संभव है? लाइन नंबर या स्टैक निशान जैसी चीजें बहुत अच्छी होंगी।


Answers

Quoting

क्या होगा यदि आपका एप्लिकेशन किसी अन्य तरीके से लॉगिंग करता है - logging मॉड्यूल का उपयोग नहीं कर रहा है?

अब, traceback का इस्तेमाल यहां किया जा सकता है।

import traceback

def log_traceback(ex, ex_traceback=None):
    if ex_traceback is None:
        ex_traceback = ex.__traceback__
    tb_lines = [ line.rstrip('\n') for line in
                 traceback.format_exception(ex.__class__, ex, ex_traceback)]
    exception_logger.log(tb_lines)
  • इसे पायथन 2 में प्रयोग करें:

    try:
        # your function call is here
    except Exception as ex:
        _, _, ex_traceback = sys.exc_info()
        log_traceback(ex, ex_traceback)
    
  • इसे पायथन 3 में प्रयोग करें:

    try:
        x = get_number()
    except Exception as ex:
        log_traceback(ex)
    

यदि आप अतिरिक्त निर्भरता का सामना कर सकते हैं तो twisted.log का उपयोग करें, आपको त्रुटियों को स्पष्ट रूप से लॉग इन करने की आवश्यकता नहीं है और यह पूरे ट्रेसबैक और समय को फ़ाइल या स्ट्रीम में वापस कर देता है।


ऐसा करने का एक साफ तरीका format_exc() का उपयोग कर रहा है और फिर प्रासंगिक भाग प्राप्त करने के लिए आउटपुट को पार्स करें:

from traceback import format_exc

try:
    1/0
except Exception:
    print 'the relevant part is: '+format_exc().split('\n')[-2]

सादर


share बारे में एक अच्छी बात यह है कि share नहीं दिखाता है कि आप एक मनमाना संदेश में गुजर सकते हैं, और लॉगिंग अभी भी सभी अपवाद विवरणों के साथ पूर्ण ट्रेसबैक दिखाएगा:

import logging
try:
    1/0
except Exception:
    logging.exception("Deliberate divide by zero traceback")

डिफ़ॉल्ट (हाल के संस्करणों में) sys.stderr को केवल प्रिंटिंग त्रुटियों के लॉगिंग व्यवहार के साथ, ऐसा लगता है:

>>> import logging
>>> try:
...     1/0
... except Exception:
...     logging.exception("Deliberate divide by zero traceback")
... 
ERROR:root:Deliberate divide by zero traceback
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: integer division or modulo by zero

यह उत्तर उपरोक्त उत्कृष्ट लोगों से बना है।

अधिकांश अनुप्रयोगों में, आप logging.exception (e) को सीधे कॉल नहीं करेंगे। सबसे अधिक संभावना है कि आपने अपने एप्लिकेशन या मॉड्यूल के लिए विशिष्ट कस्टम लॉगर परिभाषित किया है:

# Set the name of the app or module
my_logger = logging.getLogger('NEM Sequencer')
# Set the log level
my_logger.setLevel(logging.INFO)

# Let's say we want to be fancy and log to a graylog2 log server
graylog_handler = graypy.GELFHandler('some_server_ip', 12201)
graylog_handler.setLevel(logging.INFO)
my_logger.addHandler(graylog_handler)

इस मामले में, अपवाद (ई) को कॉल करने के लिए केवल लॉगर का उपयोग करें:

try:
    1/0
except Exception, e:
    my_logger.exception(e)

Exc_info विकल्पों का उपयोग करना बेहतर हो सकता है, ताकि आप त्रुटि स्तर चुन सकें (यदि आप exception उपयोग करते exception , तो यह हमेशा error दिखाएगा):

try:
    # do something here
except Exception as e:
    logging.fatal(e, exc_info=True)  # log exception info at FATAL log level

यदि आप सादा लॉग का उपयोग करते हैं - आपके सभी लॉग रिकॉर्ड इस नियम से मेल खाते हैं: one record = one line । इस नियम के बाद आप अपनी लॉग फ़ाइलों को संसाधित करने के लिए grep और अन्य टूल्स का उपयोग कर सकते हैं।

लेकिन ट्रेसबैक जानकारी बहु-रेखा है। तो मेरा जवाब इस धागे में ऊपर zangw द्वारा प्रस्तावित समाधान का विस्तारित संस्करण है। समस्या यह है कि ट्रेसबैक लाइनों में \n अंदर हो सकता है, इसलिए हमें इस लाइन के अंत से छुटकारा पाने के लिए अतिरिक्त कार्य करने की आवश्यकता है:

import logging


logger = logging.getLogger('your_logger_here')

def log_app_error(e: BaseException, level=logging.ERROR) -> None:
    e_traceback = traceback.format_exception(e.__class__, e, e.__traceback__)
    traceback_lines = []
    for line in [line.rstrip('\n') for line in e_traceback]:
        traceback_lines.extend(line.splitlines())
    logger.log(level, traceback_lines.__str__())

उसके बाद (जब आप अपने लॉग का विश्लेषण करेंगे) तो आप अपनी लॉग फ़ाइल से आवश्यक ट्रेसबैक लाइन कॉपी / पेस्ट कर सकते हैं और ऐसा कर सकते हैं:

ex_traceback = ['line 1', 'line 2', ...]
for line in ex_traceback:
    print(line)

फायदा!


सामान्य मामले के लिए जहां आपको कुछ अप्रत्याशित परिस्थितियों के जवाब में अपवाद फेंकने की आवश्यकता होती है, और आप कभी भी पकड़ने का इरादा नहीं रखते हैं, लेकिन यदि आप कभी भी ऐसा करते हैं तो वहां से डीबग करने में सक्षम होने के लिए तेज़ी से विफल होने के लिए - सबसे तार्किक लगता है AssertionError :

if 0 < distance <= RADIUS:
    #Do something.
elif RADIUS < distance:
    #Do something.
else:
    raise AssertionError("Unexpected value of 'distance'!", distance)






python exception logging exception-handling