2013-08-10 12 views
7

के फेंक विधि का उपयोग नहीं जब इस कोड है:अपवाद लेखन त्रुटि चेतावनी कभी कभी दिखाया गया है, कभी कभी जनरेटर

class MyException(Exception): 
    pass 

def gen(): 
    for i in range(3): 
    try: 
     yield i 
    except MyException: 
     print("MyException!") 


a = gen() 
next(a) 
a.throw(MyException) 

इस कोड चल रहा है:

$ python3.3 main.py 
MyException! 
$ python3.3 main.py 
MyException! 
Exception TypeError: TypeError('catching classes that do not inherit from BaseException is not allowed',) in <generator object gen at 0xb712efa4> ignored 
$ python3.3 main.py 
MyException! 
$ python3.3 main.py 
MyException! 
$ python3.3 main.py 
MyException! 
Exception TypeError: TypeError('catching classes that do not inherit from BaseException is not allowed',) in <generator object gen at 0xb714afa4> ignored 

बात जो मुझे समझ नहीं आता क्यों है कभी-कभी इस Exception TypeError चेतावनी मुद्रित की जाती है। क्या कस्टम अपवाद के साथ कुछ गड़बड़ है?

उत्तर

11

आप कहीं भी __del__ हुक गलत व्यवहार देख रहे हैं।

TypeError जबकि नीचे बंद, के रूप में अजगर दुभाषिया बाहर निकलने है कुछ हट जाता है और किसी भी अपवाद एक __del__ Deconstructor हुक में फेंक दिया अनदेखा किया जा रहा है (लेकिन मुद्रित कर रहे हैं) फेंक दिया जा रहा है।

बाहर निकलने पर, पायथन None पर सबकुछ पुनर्निर्मित करके नामस्थान में सबकुछ साफ़ करता है, लेकिन जिस क्रम में यह होता है वह सेट नहीं होता है। अभी भी चलने वाले जनरेटर बंद हैं (a.close() कहा जाता है) हटाए जाने पर, जो जेनरेटर में GeneratorExit अपवाद को ट्रिगर करता है, जो आपके except MyException: लाइन के खिलाफ पाइथन परीक्षण करता है। यदि, हालांकि, MyException में पहले से ही को साफ़ कर दिया गया है और पायथन except None:TypeError फेंक दिया गया है और आप उस संदेश को मुद्रित करते हैं।

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

MyException = None 
del a 

आप list(a) का उपयोग करें और अजगर रास्ते से पहले a.close() साथ जनरेटर बंद जनरेटर के बाकी उपभोग करते हैं, या स्पष्ट रूप से और हटाता MyException, त्रुटि संदेश चला जाता है।

एक और काम के आसपास GeneratorExit पहले संभाल करने होगा:

def gen(): 
    for i in range(3): 
    try: 
     yield i 
    except GeneratorExit: 
     return 
    except MyException: 
     print("MyException!") 

और अजगर अगले except हैंडलर का मूल्यांकन नहीं होंगे।

त्रुटि को पायथन 3.2 या उससे पहले के साथ पुन: उत्पन्न नहीं किया जा सकता है, इसलिए ऐसा लगता है कि hash randomization (पायथन 3.3 में पेश किया गया) ऑर्डर ऑब्जेक्ट्स को यादृच्छिक करता है; यह निश्चित रूप से बताता है कि आप केवल पर कुछ पर त्रुटि क्यों देखते हैं, लेकिन पहले पायथन पर नहीं है जहां हैश ऑर्डर तय किया गया है।

ध्यान दें कि .__del__() हुक और अजगर में अन्य वैश्विक वस्तुओं की बातचीत .__del__() documentation में एक बड़ा लाल चेतावनी के साथ प्रलेखित है:

Warning: Due to the precarious circumstances under which __del__() methods are invoked, exceptions that occur during their execution are ignored, and a warning is printed to sys.stderr instead. Also, when __del__() is invoked in response to a module being deleted (e.g., when execution of the program is done), other globals referenced by the __del__() method may already have been deleted or in the process of being torn down (e.g. the import machinery shutting down). For this reason, __del__() methods should do the absolute minimum needed to maintain external invariants. Starting with version 1.5, Python guarantees that globals whose name begins with a single underscore are deleted from their module before other globals are deleted; if no other references to such globals exist, this may help in assuring that imported modules are still available at the time when the __del__() method is called.

+0

पायथन में 2.7 चेतावनी कभी नहीं दिखायी जाती है और कोड पोस्ट कोड में एकमात्र कोड है। – scdmb

+0

पायथन 3.2 भी प्रिंट नहीं करता है। –

+0

'del' के साथ, अधिक तार्किक NameError उठाया गया है। –

1

मैं इस एक ही गलती अंतर के साथ, विंडोज पर पायथन 3.3 में हो रही थी कि मैं अपनी फाइल में अपवाद को परिभाषित कर रहा था।

TypeError: catching classes that do not inherit from BaseException is not allowed.

बदलने import FooErrorfrom FooError import * को समस्या का समाधान हो:

$ cat FooError.py 
class FooError(Exception): 
    pass 

$ cat application.py 
import FooError 
try: 
    raise FooError('Foo not bar!') 
Except FooError as e: 
    print(e) 

यह अपवाद है कि मैं हो रही थी था: ये मेरी कोड फ़ाइलों थे। यहाँ स्पष्टता की खातिर, अंतिम कोड है:

$ cat FooError.py 
class FooError(Exception): 
    pass 

$ cat application.py 
from FooError import * 
try: 
    raise FooError('Foo not bar!') 
Except FooError as e: 
    print(e) 
+0

यदि आपने केवल मॉड्यूल को पकड़ नहीं लिया है तो FooError.FooError को छोड़कर काम किया होगा :) –

+0

@GuyL: धन्यवाद! मेरे पास परीक्षण करने के लिए एक विंडोज मशीन नहीं है, लेकिन मुझे लगता है कि 'FooError आयात FooError' से भी काम किया होगा। – dotancohen

1

मैं एक ही समस्या थी - लेकिन मैं अपवाद वर्ग के लिए आयात याद आ रही थी। तो दुभाषिया ने खंड को छोड़कर कक्षा को हल नहीं किया।

तो बस आयात जोड़ें और उम्मीद है कि सब कुछ काम करेगा।

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