2014-08-28 6 views
6

को छोड़कर एक अलग से पकड़ा जाता है मैं निम्नलिखित कोड:अपवाद दो बार मार डाला जाता है और इसे ब्लॉक

file1.py

from file2 import tfun 

class TestException(Exception): 
    pass 

try: 
    print 'I am running' 
    tfun() 
except TestException as e: 
    print 'I am caught' 
    print type(e) 
except Exception as e: 
    print 'I am generally caught' 
    print type(e) 

file2.py

def tfun(): 
    from file1 import TestException 
    raise TestException() 

और python file1.py से आउटपुट निम्न है:

I am running 
I am running 
I am caught 
<class 'file1.TestException'> 
I am generally caught 
<class 'file1.TestException'> 

सबसे पहले इस मामले में कोड दो बार निष्पादित क्यों किया जाता है? मैं समझ सकता हूं कि आयात रिकर्सिव है लेकिन स्क्रिप्ट का कोड फिर से निष्पादित क्यों होता है?

दूसरा, दूसरी बार यह उसी except ब्लॉक द्वारा पकड़ा नहीं जा रहा है, भले ही यह पहली बार जैसा ही हो, जिसे मुझे स्पष्टीकरण भी नहीं मिल रहा है।

अंत में, मैं इस समस्या के लिए एक नई फ़ाइल में कुछ भी स्थानांतरित किए बिना कामकाज खोजने की कोशिश कर रहा हूं लेकिन मुझे ऐसा लगता है कि यह कोई नहीं है। क्या इस समस्या को खत्म करना संभव है?

संपादित

दूसरे प्रश्न के लिए मुझे एहसास हुआ कि ऐसा इसलिए है क्योंकि कोड मॉड्यूल स्तर के अंदर है।

+3

+1 एक संक्षिप्त, पूर्ण, स्टैंडअलोन प्रोग्राम के लिए +1 जो समस्या को प्रदर्शित करता है। रेफरी: http://stackoverflow.com/help/mcve और http://SSCCE.org –

उत्तर

7

आप एक स्क्रिप्ट के रूप में एक मॉड्यूल (अर्थात बल्कि यह आयात करने से, दुभाषिया के लिए इसका नाम दे) चलाते हैं, तो यह मॉड्यूल का नाम __main__ के तहत भरी हुई है।

यदि आप अपने प्रोग्राम से एक ही मॉड्यूल आयात करते हैं, तो इसे अपने वास्तविक नाम के तहत पुनः लोड और पुनः प्राप्त किया जाता है। यदि आप सावधान नहीं हैं, तो आप चीजों को दो बार खत्म कर सकते हैं।

http://effbot.org/zone/import-confusion.htm

आपका file1.py दो बार लोड कर रहे हैं, दो अलग-अलग मॉड्यूल के रूप में। पहली बार यह अपने आदेश पंक्ति के एक reesult के रूप में भरी हुई है:

python file1.py 

उस मामले में, file1.py मुख्य मॉड्यूल, __main__ के रूप में लोड किया जा रहा है।

दूसरी बार जब आप अपने आयात बयान का एक परिणाम के रूप में यह लोड कर रहे हैं:

from file1 import TestException 

उस मामले में, file1.py मॉड्यूल file1 के रूप में लोड किया जा रहा है।

क्योंकि फ़ाइल 1.py दो अलग मॉड्यूल के रूप में लोड किया जा रहा है, इसमें सबकुछ की दो अलग-अलग प्रतियां हैं। विशेष रूप से __main__.TestExceptionfile1.TestException से अलग है।

तो, __main__ अंदर, लाइन:

except TestException as e: 

__main__.TestException के रूप में भी tfun()__file1__.TestException बढ़ा रहा है बढ़ रहा है। file1 के अंदर, वही पंक्ति file1.TestException पकड़ रही है।

पूर्व मामले में, प्रकार मेल नहीं खाते हैं और except: खंड नहीं चलाया जाता है; बाद के मामले में प्रकार मिलान करता है और except: खंड चलाया जाता है।

शायद इस कार्यक्रम में यह और अधिक स्पष्ट क्या हो रहा है बना सकते हैं:

from file2 import tfun 

class TestException(Exception): 
    pass 

try: 
    print 'I am calling file2.tfun from', __name__ 
    tfun() 
    print 'I have called file2.tfun from', __name__ 
except TestException as e: 
    print 'I am caught in %s'%(__name__) 
    print type(e), TestException 
except Exception as e: 
    print 'I am generally caught in %s'%__name__ 
    print type(e), TestException 
print 'I am exiting from',__name__ 

परिणाम:

$ python file1.py 
I am calling file2.tfun from __main__ 
I am calling file2.tfun from file1 
I am caught in file1 
<class 'file1.TestException'> <class 'file1.TestException'> 
I am exiting from file1 
I am generally caught in __main__ 
<class 'file1.TestException'> <class '__main__.TestException'> 
I am exiting from __main__ 

एक सरल समाधान का file2.py संशोधित करने के लिए है:

def tfun(): 
    from __main__ import TestException 
    raise TestException() 

परिणाम :

$ python file1.py 
I am calling file2.tfun from __main__ 
I am caught in __main__ 
<class '__main__.TestException'> <class '__main__.TestException'> 
I am exiting from __main__ 
+2

+1 '__main __। TestException' और 'file1.TestException' के बीच भेद सबसे कठिन हिस्सा है, मुझे लगता है। – chepner

संबंधित मुद्दे