इस में हो सकता है डेबियन निचोड़ पर अजगर 2.6.6 (डिफ़ॉल्ट) के साथ है। निम्नलिखित पायथन कोड पर विचार करें।अपवाद संचालन जब त्रुटियों मुख्य कार्यक्रम में या सफाई
import sys
try:
raise Exception("error in main")
pass
except:
exc_info = sys.exc_info()
finally:
try:
print "cleanup - always run"
raise Exception("error in cleanup")
except:
import traceback
print >> sys.stderr, "Error in cleanup"
traceback.print_exc()
if 'exc_info' in locals():
raise exc_info[0], exc_info[1], exc_info[2]
print "exited normally"
प्राप्त त्रुटि
Error in cleanup
Traceback (most recent call last):
File "<stdin>", line 10, in <module>
Exception: error in cleanup
cleanup - always run
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
Exception: error in main
विचार एक स्थिति है जहाँ या तो कुछ कोड या कि कोड की सफाई (जो हमेशा चलाया जाता है) या दोनों, एक त्रुटि देता है से निपटने के लिए है। इसके बारे में कुछ चर्चा है, उदाहरण के लिए, Re-raising Exceptions में इयान बेकिंग द्वारा। उस पोस्ट के अंत में, (Update:
देखें) उनके द्वारा वर्णित कोड + रोलबैक/वापस लाएं के इसी तरह के मामले को संभालने के लिए कैसे (केवल गलती की स्थिति में आ जाते है)।
मैंने इसके साथ झुकाया और उपरोक्त कोड के साथ आया, जो एक राक्षसीता है। विशेष रूप से, यदि केवल क्लीनअप में एक त्रुटि (raise Exception("error in main")
पर टिप्पणी कर रहा है), कोड अभी भी सामान्य रूप से बाहर निकलता है, हालांकि यह एक ट्रेसबैक प्रिंट करता है। वर्तमान में, मैं गैर-सफाई त्रुटि प्राथमिकता दे रहा हूं, इसलिए यह प्रोग्राम को रोकता है।
आदर्श रूप में मैं प्रोग्राम को रोकने के लिए या तो त्रुटि करना चाहता हूं, लेकिन ऐसा व्यवस्थित करना आसान नहीं लगता है। पाइथन केवल एक त्रुटि उठाना चाहता है, अगर किसी को भी खो देता है, और डिफ़ॉल्ट रूप से यह आमतौर पर आखिरी है। इससे पुन: प्रयास करने से ऊपर की तरह संकल्प बढ़ जाता है।
इसके अलावा locals()
का उपयोग थोड़ा बदसूरत है। क्या कोई बेहतर कर सकता है?
संपादित करें: srgerg's answer ने मुझे संदर्भ प्रबंधकों और with
कीवर्ड की धारणा के साथ पेश किया। PEP 343 के अलावा, प्रलेखन के अन्य प्रासंगिक बिट मैं (किसी विशेष क्रम में) कर रहे हैं पाया। Context Manager Types, The with statement, और http://docs.python.org/reference/datamodel.html#context-managers। यह निश्चित रूप से इस के लिए पिछले दृष्टिकोणों से, यानी स्पेगेटी कोड trys, excepts, और finallys को शामिल पर एक बड़ा सुधार की तरह लगता है।
संक्षेप में, वहाँ दो चीजें हैं जो मैं इस तरह के एक समाधान चाहते हैं मुझे देने के लिए कर रहे हैं।
या तो मुख्य कोड में या सफाई में एक अपवाद के लिए क्षमता ने रास्ते में ही कार्यक्रम को रोकने के लिए। संदर्भ प्रबंधक यह करते हैं, क्योंकि यदि लूप के शरीर में अपवाद है और का शरीर बाहर निकलें नहीं है, तो उस अपवाद का प्रचार किया जाता है। यदि बाहर निकलें एक अपवाद फेंकता है और लूप के साथ शरीर नहीं है तो प्रचारित किया जाता है। यदि दोनों एक अपवाद फेंकते हैं, तो बाहर निकलें अपवाद प्रसारित किया जाता है और जबकि लूप के शरीर से एक दबाया जाता है। यह सब, Context Manager Types से अर्थात प्रलेखित है
contextmanager। बाहर निकलें (exc_type, exc_val, exc_tb)
रनटाइम संदर्भ से बाहर निकलें और एक बूलियन ध्वज लौटाएं जो दर्शाता है कि क्या हुआ कोई अपवाद दबाया जाना चाहिए। [...] इस विधि से एक वास्तविक मूल्य लौटने से बयान के साथ अपवाद को दबाने और कथन के साथ तुरंत कथन के बाद निष्पादन जारी रहेगा। अन्यथा इस विधि के बाद निष्पादन समाप्त होने के बाद अपवाद जारी है। इस विधि के निष्पादन के दौरान होने वाली अपवाद
कथन के साथ किसी भी अपवाद को प्रतिस्थापित करेंगे। [...] पारित अपवाद को स्पष्ट रूप से कभी नहीं बदला जाना चाहिए। इसके बजाए, इस विधि को पर झूठा मान वापस करना चाहिए, यह इंगित करता है कि विधि सफलतापूर्वक पूर्ण हो गई है और उठाए गए अपवाद को दबाना नहीं चाहता है।वहाँ दोनों स्थानों में अपवाद हैं, तो मैं ट्रेस बैक दोनों से को देखने के लिए, भले ही तकनीकी रूप से केवल एक अपवाद फेंक दिया जाता है चाहता हूँ। इसका कारण यह है कि दोनों एक अपवाद है, तो बाहर निकलने अपवाद प्रचारित किया जाता है फेंक, प्रयोग के आधार पर सही है, लेकिन जबकि पाश के शरीर से ट्रैस बैक अभी भी srgerg's answer के रूप में, प्रिंट होता है। हालांकि, मुझे यह दस्तावेज कहीं भी नहीं मिला है, जो असंतोषजनक है।
import sys, traceback def excepthook(*exc_info): print "cleanup - always run" raise Exception("error in cleanup") traceback.print_exception(*exc_info) sys.excepthook = excepthook raise Exception("error in main")
उदाहरण आउटपुट:
धन्यवाद, यह मेरे लिए एक बिल्कुल नया विचार है। क्या विचार साफ है जहां आपने अपवाद बढ़ाया है ("अपवाद __exit __ के दौरान हुआ") '? यदि हां, तो क्या आप एक उचित 'प्रिंट "क्लीनअप जोड़ सकते हैं - हमेशा" 'या इसी तरह से चलाएं? –
मैंने अनुरोध के रूप में प्रिंट स्टेटमेंट जोड़ा है। – srgerg
धन्यवाद, srgerg। मैं पीईपी पढ़ रहा हूँ। मुझे नहीं लगता कि मैंने पहले 'कीवर्ड' के बारे में सुना या देखा था, लेकिन हो सकता है कि मैं सिर्फ ध्यान नहीं दे रहा था। क्या कोई व्यक्ति प्रवेश या निकास समारोह में क्लीनअप कोड डाल देगा, या इससे कोई फर्क नहीं पड़ता है? –