एक चर में ट्रेसबैक / sys.exc_info () मान कैसे बचाएं?


127

मैं त्रुटि और ट्रेसबैक विवरण के नाम को एक चर में सहेजना चाहता हूं। यहाँ मेरा प्रयास है।

import sys
try:
    try:
        print x
    except Exception, ex:
        raise NameError
except Exception, er:
    print "0", sys.exc_info()[0]
    print "1", sys.exc_info()[1]
    print "2", sys.exc_info()[2]

आउटपुट:

0 <type 'exceptions.NameError'>
1 
2 <traceback object at 0xbd5fc8>

वांछित आउटपुट:

0 NameError
1
2 Traceback (most recent call last):
  File "exception.py", line 6, in <module>
    raise NameError

PS मुझे पता है कि यह ट्रेसबैक मॉड्यूल का उपयोग करके आसानी से किया जा सकता है, लेकिन मैं यहां sys.exc_info () [2] ऑब्जेक्ट का उपयोग जानना चाहता हूं।


क्या आपने sys.exc_info () [x] .__ str __ () को छापने का प्रयास किया?
झूमक

3
आपके कार्यक्रम में क्या चल रहा है, यह आप गलत समझ सकते हैं: जिसे आप "sys.exc_info () [2] ऑब्जेक्ट" के रूप में संदर्भित करते हैं, ट्रेसबैक ऑब्जेक्ट का एक उदाहरण है (= आप पहले से ही ट्रेसबैक मॉड्यूल का उपयोग कर रहे हैं)। अब, आप ट्रेसबैक मॉड्यूल में सहायक कार्यों का उपयोग किए बिना उस ऑब्जेक्ट में हेरफेर कर सकते हैं, लेकिन यह इस तथ्य को नहीं बदलता है कि आप अभी भी इसका उपयोग कर रहे हैं। :)
मैक

1
तो @ एमएसी कृपया हेल्पर फ़ंक्शन का उपयोग किए बिना या बिना इस ऑब्जेक्ट से मूल्य तक पहुंचने में मेरी मदद करें।
codersofthedark

1
@dragosrsupercool - जैसा कि मैंने नीचे अपने उत्तर में उल्लेख किया है, आपको ट्रेसबैक प्रलेखन को देखना चाहिए । मैंने एक उदाहरण प्रदान किया कि डेटा को कैसे पुनर्प्राप्त किया जाता है, लेकिन ऑब्जेक्ट के अन्य तरीके हैं जो आपको अपवाद नाम, कोड की पंक्ति आदि को निकालने की अनुमति देते हैं ... सही एक वास्तव में इस बात पर निर्भर करता है कि आप किस प्रकार से हेरफेर करना चाहते हैं मूल्य बाद में ...
मैक

1
एक अन्य प्रश्न का मेरा उत्तर विवरणों को स्पष्ट करने में मदद कर सकता है - लिंक के साथ! डिब्बाबंद तारों के लिए, मानक पुस्तकालय ट्रेसबैक मॉड्यूल ठीक लगता है। यदि आप विवरण प्राप्त करना चाहते हैं, तो <python install path>/Lib/traceback.pyअधिक जानकारी के लिए स्रोत ( ) पढ़ें ।
अजगर का बच्चा

जवाबों:


180

यह मेरा इसे करने का तरीका है:

>>> import traceback
>>> try:
...   int('k')
... except:
...   var = traceback.format_exc()
... 
>>> print var
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ValueError: invalid literal for int() with base 10: 'k'

हालाँकि आपको ट्रेसबैक डॉक्यूमेंट पर एक नज़र डालनी चाहिए , क्योंकि आपको वहाँ अधिक उपयुक्त तरीके मिल सकते हैं, जो इस बात पर निर्भर करता है कि आप बाद में अपने कंप्यूटर को कैसे प्रोसेस करना चाहते हैं ...


1
मैं ट्रेसबैक मॉड्यूल का उपयोग किए बिना एक विधि की मांग कर रहा था। क्या कोई है जो हम इस वस्तु संदर्भ से केवल ट्रेस-बैक विवरण प्रिंट कर सकते हैं? sys.exc_info () [2]
th३

ठीक है, इसीलिए मुझे लगा कि हम sys.exc_info () [2] .format_exc () जैसे कुछ भी कर सकते हैं, लेकिन यह काम नहीं करता है .. इस प्रकार, मुझे आश्चर्य है कि मैं ट्रेस-बैक ऑब्जेक्ट sys .exc_info () से मूल्य कैसे निकाल सकता हूं। [2]। कोई उपाय?
कोडर्सोफ्थेडार्क

1
sys.exc_info () [2] .tb_text त्रुटि का पालन करता है -> विशेषता: 'ट्रेसबैक' ऑब्जेक्ट में कोई विशेषता नहीं है 'tb_text'
codersofthedark

4
@dragosrsupercool - sys.exc_info()[2].tb_frame.f_code.co_names[3], लेकिन इसका कोई मतलब नहीं है ... यदि tracebackमानक पुस्तकालय में एक मॉड्यूल कहा जाता है, तो इसका एक कारण है ... :)
mac

2
@codersofthedark traceback.format_exception(*sys.exc_info())इसे करने का तरीका है। लेकिन यह कार्यात्मक रूप से इसके बराबर है traceback.format_exc()
wizzwizz4

25

sys.exc_info () तीन मूल्यों (प्रकार, मान, ट्रेसबैक) के साथ एक टपल लौटाता है।

  1. यहाँ प्रकार अपवाद अपवाद प्रकार को संभाला जा रहा है
  2. मूल्य वे तर्क हैं जो अपवाद वर्ग के निर्माणकर्ता को दिए जा रहे हैं
  3. ट्रेसबैक में स्टैक जानकारी होती है जैसे कि अपवाद कहां हुआ आदि।

उदाहरण के लिए, निम्नलिखित कार्यक्रम में

try:

    a = 1/0

except Exception,e:

    exc_tuple = sys.exc_info()

अब यदि हम टपल प्रिंट करते हैं तो मान इस प्रकार होंगे।

  1. exc_tuple [0] मान " ZeroDivisionError " होगा
  2. exc_tuple [1] मान " पूर्णांक विभाजन या शून्य से modulo " होगा (स्ट्रिंग अपवाद स्वरूप पैरामीटर के रूप में पारित किया गया है)
  3. exc_tuple [2] मान "ट्रैकबैक ऑब्जेक्ट एट (कुछ मेमोरी एड्रेस) " होगा

उपरोक्त विवरण को केवल स्ट्रिंग प्रारूप में अपवाद को मुद्रित करके प्राप्त किया जा सकता है।

print str(e)

Python3 के लिए, exc_tuple [1] (उर्फ मान) अपवाद का उदाहरण है, न कि "स्ट्रिंग को पैरामीटर के रूप में पारित किया गया"। देखें: docs.python.org/3/library/sys.html#sys.exc_info
शि

क्या इसे "अपवाद को छोड़कर e:" नहीं होना चाहिए?
हेनरिक

20

traceback.extract_stack()यदि आप मॉड्यूल और फ़ंक्शन नाम और लाइन नंबरों के लिए सुविधाजनक पहुंच चाहते हैं तो इसका उपयोग करें ।

उपयोग करें ''.join(traceback.format_stack())यदि आप सिर्फ एक स्ट्रिंग चाहते हैं जो traceback.print_stack()आउटपुट की तरह दिखता है ।

ध्यान दें कि ''.join()आपके साथ भी एक मल्टी-लाइन स्ट्रिंग मिलेगा, क्योंकि इसमें तत्व format_stack()होते हैं \n। नीचे उत्पादन देखें।

याद करना import traceback

यहाँ से आउटपुट है traceback.extract_stack()। पठनीयता के लिए स्वरूपण जोड़ा गया।

>>> traceback.extract_stack()
[
   ('<string>', 1, '<module>', None),
   ('C:\\Python\\lib\\idlelib\\run.py', 126, 'main', 'ret = method(*args, **kwargs)'),
   ('C:\\Python\\lib\\idlelib\\run.py', 353, 'runcode', 'exec(code, self.locals)'),
   ('<pyshell#1>', 1, '<module>', None)
]

यहाँ से आउटपुट है ''.join(traceback.format_stack())। पठनीयता के लिए स्वरूपण जोड़ा गया।

>>> ''.join(traceback.format_stack())
'  File "<string>", line 1, in <module>\n
   File "C:\\Python\\lib\\idlelib\\run.py", line 126, in main\n
       ret = method(*args, **kwargs)\n
   File "C:\\Python\\lib\\idlelib\\run.py", line 353, in runcode\n
       exec(code, self.locals)\n  File "<pyshell#2>", line 1, in <module>\n'

4

जब आप अपवाद वस्तु या ट्रेसबैक ऑब्जेक्ट को अपवाद हैंडलर से बाहर निकालते हैं, तो सावधान रहें क्योंकि यह परिपत्र संदर्भ का कारण बनता है और gc.collect()इकट्ठा करने में विफल रहेगा। यह ipython / jupyter नोटबुक वातावरण में एक विशेष समस्या प्रतीत होती है जहाँ ट्रेसबैक ऑब्जेक्ट को सही समय पर साफ़ नहीं किया जाता है और यहाँ तक कि अनुभाग gc.collect()में एक स्पष्ट कॉल finallyभी कुछ नहीं करता है। और यह एक बहुत बड़ी समस्या है यदि आपके पास कुछ विशाल वस्तुएं हैं जिनकी वजह से उनकी मेमोरी पुनः प्राप्त नहीं होती है (उदाहरण के लिए मेमोरी अपवादों से बाहर CUDA जो w / o इस समाधान को पुनर्प्राप्त करने के लिए पूर्ण कर्नेल पुनरारंभ की आवश्यकता होती है)।

सामान्य तौर पर यदि आप ट्रेसबैक ऑब्जेक्ट को बचाना चाहते हैं, तो आपको इसे संदर्भ से साफ़ करने की आवश्यकता है locals(), जैसे:

import sys, traceback, gc
type, val, tb = None, None, None
try:
    myfunc()
except:
    type, val, tb = sys.exc_info()
    traceback.clear_frames(tb)
# some cleanup code
gc.collect()
# and then use the tb:
if tb:
    raise type(val).with_traceback(tb)

ज्यूपिटर नोटबुक के मामले में, आपको यह करना होगा कि अपवाद हैंडलर के अंदर बहुत कम से कम:

try:
    myfunc()
except:
    type, val, tb = sys.exc_info()
    traceback.clear_frames(tb)
    raise type(val).with_traceback(tb)
finally:
    # cleanup code in here
    gc.collect()

अजगर 3.7 के साथ परीक्षण किया गया।

ps ipython या jupyter नोटबुक env के साथ समस्या यह है कि इसमें %tbजादू है जो ट्रेसबैक को बचाता है और बाद में किसी भी बिंदु पर उपलब्ध कराता है। और इसके परिणामस्वरूप locals()ट्रेसबैक में भाग लेने वाले सभी फ़्रेमों में से किसी को भी मुक्त नहीं किया जाएगा, जब तक कि नोटबुक बाहर नहीं निकलता है या कोई अन्य अपवाद पहले से संग्रहीत बैकट्रेस को अधिलेखित कर देगा। यह बहुत समस्याग्रस्त है। यह अपने फ्रेम को साफ करते हुए ट्रेसबैक डब्ल्यू / ओ को स्टोर नहीं करना चाहिए। यहाँ ठीक किया गया


3

Exception.with_traceback()फ़ंक्शन में ऑब्जेक्ट का उपयोग पैरामीटर के रूप में किया जा सकता है :

except Exception as e:
    tb = sys.exc_info()
    print(e.with_traceback(tb[2]))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.