जब मैं एक अपवाद को पकड़ता हूं, तो मुझे टाइप, फ़ाइल और लाइन नंबर कैसे मिलेगा?


252

एक अपवाद को पकड़ने जो इस तरह से प्रिंट होता है:

Traceback (most recent call last):
  File "c:/tmp.py", line 1, in <module>
    4 / 0
ZeroDivisionError: integer division or modulo by zero

मैं इसे प्रारूपित करना चाहता हूं:

ZeroDivisonError, tmp.py, 1

5
अंतर्निहित ट्रेसबैक मॉड्यूल का उपयोग करें ।
नेड डिली

यह कोड की लाइन को प्रिंट करने में भी सहायक हो सकता है, जहां अपवाद हुआ: देखें stackoverflow.com/questions/14519177/…
Apogentus

जवाबों:


381
import sys, os

try:
    raise NotImplementedError("No error")
except Exception as e:
    exc_type, exc_obj, exc_tb = sys.exc_info()
    fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
    print(exc_type, fname, exc_tb.tb_lineno)

51
आपको स्थानीय वेरिएबल्स में sys.exc_info () को अनपैक करने के बारे में सावधान रहना चाहिए, क्योंकि अगर आपको हैंडलर को छोड़कर कोई अपवाद मिलता है, तो स्थानीय वेरिएंट को एक परिपत्र संदर्भ में रखा जा सकता है और GC'd नहीं। इसके बजाय सर्वोत्तम अभ्यास हमेशा स्लाइस को sys.exc_info () से दूर करना है। या ट्रेसबैक जैसे अन्य मॉड्यूल का उपयोग करें, जैसा कि अन्य पोस्टरों ने सुझाव दिया है।
डैनियल प्राइडेन

1
क्या tb सिर्फ exc_tb है? और os.path.split (blabla) [1] os.path.basename (बालबल)
सनकिआंग है

4
@Basj: sys.exc_info () [0] .__ name__ से आपको टाइप का सादा नाम मिलता है।
जोहान्स ओवरमैन

5
@DanielPryden पायथन डॉक्स भी एक ही अनपैकिंग
उपयोगकर्ता

3
@RobM: हाँ, यह थ्रेड-सुरक्षित है। sys.exc_info()पिछली API में थ्रेड-सुरक्षा समस्याओं से निपटने के लिए शुरू किया गया था। इसका उत्पादन वर्तमान थ्रेड और वर्तमान स्टैक फ्रेम दोनों के लिए विशिष्ट है।
user2357112

126

सबसे सरल रूप जिसने मेरे लिए काम किया।

import traceback

try:
    print(4/0)
except ZeroDivisionError:
    print(traceback.format_exc())

उत्पादन

Traceback (most recent call last):
  File "/path/to/file.py", line 51, in <module>
    print(4/0)
ZeroDivisionError: division by zero

Process finished with exit code 0

7
जब तक ऑप
वांट

5
इसके बारे में क्या मजबूत है?
19

1
@ जूल हे, मुझे भी कभी-कभी फैंसी शब्दों का उपयोग करना पसंद है :)
ऋषव

साफ और प्रभावी। साझा करने के लिए धन्यवाद :)
हिमांशु गौतम

49

ट्रेसबैक.फॉर्मैट_एक्ससेप्शन () और कहा / संबंधित कार्यों के लिए स्रोत (Py v2.7.3) बहुत मदद करता है। शर्म की बात है, मैं हमेशा स्रोत को पढ़ने के लिए भूल जाते हैं । मैंने केवल व्यर्थ में इसी तरह के विवरण की खोज के बाद ऐसा किया। एक साधारण प्रश्न, "एक अपवाद के लिए अजगर के रूप में एक ही आउटपुट को फिर से कैसे बनाया जाए, सभी समान विवरणों के साथ?" यह किसी को भी 90 +% मिलेगा जो भी वे खोज रहे हैं। निराश होकर, मैं इस उदाहरण के साथ आया हूं। मुझे उम्मीद है कि यह दूसरों की मदद करता है। (यह यकीन है कि मेरी मदद की? ;-)

import sys, traceback

traceback_template = '''Traceback (most recent call last):
  File "%(filename)s", line %(lineno)s, in %(name)s
%(type)s: %(message)s\n''' # Skipping the "actual line" item

# Also note: we don't walk all the way through the frame stack in this example
# see hg.python.org/cpython/file/8dffb76faacc/Lib/traceback.py#l280
# (Imagine if the 1/0, below, were replaced by a call to test() which did 1/0.)

try:
    1/0
except:
    # http://docs.python.org/2/library/sys.html#sys.exc_info
    exc_type, exc_value, exc_traceback = sys.exc_info() # most recent (if any) by default

    '''
    Reason this _can_ be bad: If an (unhandled) exception happens AFTER this,
    or if we do not delete the labels on (not much) older versions of Py, the
    reference we created can linger.

    traceback.format_exc/print_exc do this very thing, BUT note this creates a
    temp scope within the function.
    '''

    traceback_details = {
                         'filename': exc_traceback.tb_frame.f_code.co_filename,
                         'lineno'  : exc_traceback.tb_lineno,
                         'name'    : exc_traceback.tb_frame.f_code.co_name,
                         'type'    : exc_type.__name__,
                         'message' : exc_value.message, # or see traceback._some_str()
                        }

    del(exc_type, exc_value, exc_traceback) # So we don't leave our local labels/objects dangling
    # This still isn't "completely safe", though!
    # "Best (recommended) practice: replace all exc_type, exc_value, exc_traceback
    # with sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]

    print
    print traceback.format_exc()
    print
    print traceback_template % traceback_details
    print

इस प्रश्न के विशिष्ट उत्तर में:

sys.exc_info()[0].__name__, os.path.basename(sys.exc_info()[2].tb_frame.f_code.co_filename), sys.exc_info()[2].tb_lineno

1
परिवर्तन 'message' : exc_value.messageकरने के लिए 'message' : str(exc_value)के लिए py3
user2682863

34

यहां अपवाद की लाइन संख्या दिखाने का एक उदाहरण है जहां अपवाद होता है।

import sys
try:
    print(5/0)
except Exception as e:
    print('Error on line {}'.format(sys.exc_info()[-1].tb_lineno), type(e).__name__, e)

print('And the rest of program continues')
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.