मेरे पास इस तरह का कोड है:

class Foo:
    foo_const = function_which_throws_something()

ऐसे अपवाद को कैसे कैप्चर करें? क्या यह सभी के लिए संभव है?

0
Maciej Wawrzyńczuk 27 मार्च 2018, 14:01

4 जवाब

सबसे बढ़िया उत्तर

आईएमएचओ, एक फ़ंक्शन का निष्पादन जो परिभाषा समय पर अपवाद उठा सकता है, एक संदिग्ध डिज़ाइन है। यह निश्चित रूप से पायथन भाषा द्वारा अनुमत है क्योंकि एक def कथन निष्पादन योग्य है, लेकिन यह पठनीयता में सुधार नहीं करता है।

मेरी सलाह होगी कि वर्ग परिभाषा के बाद बाद में कार्य निष्पादित करें:

# definition
class Foo:
    foo_const = None       # default initialization in case of problem...

    @classmethod
    def init_foo(cls):
        cls.foo_const = function_which_throws_something()

# initialization
try:
    Foo.init_foo()
except:
    # process the exceptional condition
    ...

इस तरह, कक्षा हमेशा बनाई जाती है, आप केवल अपवाद को संसाधित कर सकते हैं और कॉन्स का डिफ़ॉल्ट मान होता है।

लेकिन अगर आप आईएमओ कम समझदार कोड के बावजूद कम उत्पादन करना चाहते हैं, तो आप यह कर सकते हैं:

try:
    class Foo:
        foo_const = function_which_throws_something()
except:
    class Foo:
        foo_const = None
    # further exception processing
    ...

उपरोक्त कोड किसी भी अपवाद को पकड़ने के लिए कच्चे except का उपयोग करता है जिसे टाला जाना चाहिए, यदि केवल SomeException फेंका जा सकता है, तो आपको इसका उपयोग करना चाहिए:

try:
   ...
except SomeException:           # or except SomeException as e:
   ...
1
Serge Ballesta 27 मार्च 2018, 11:53

पायथन में बाइटकोड के संकलन को छोड़कर सबकुछ रनटाइम पर होता है। IOW, class एक निष्पादन योग्य कथन है। जब दुभाषिया एक class स्टेटमेंट तक पहुंचता है, तो यह एक नेमस्पेस सेट करता है, पूरे class स्टेटमेंट के बॉडी को उस नेमस्पेस के भीतर निष्पादित करता है, और उस नेमस्पेस में परिभाषित सभी नामों को क्लास एट्रीब्यूट के रूप में उपयोग करता है। फिर यह type() को वर्ग के नाम, आधारों और एकत्रित नामस्थानों के साथ कॉल करता है, और नव निर्मित वर्ग वस्तु (उदाहरण type या जो भी कस्टम मेटाक्लास) को कक्षा के नाम से जोड़ता है।

इसका मतलब यह है कि आप क्लास स्टेटमेंट के भीतर किसी भी मनमाने कोड को निष्पादित कर सकते हैं - कोशिश करें/छोड़कर, लूप, सशर्त, जो भी वैध पायथन कोड, जिसमें आपके उदाहरण में, फ़ंक्शन को कॉल करना शामिल है। और वास्तव में आपके मामले में यह "वर्ग परिभाषा" नहीं है जो अपवाद उठाता है लेकिन जिस फ़ंक्शन को आप class कथन के भीतर से कॉल करते हैं, ताकि आप स्पष्ट रूप से कॉल को एक कोशिश/ब्लॉक को छोड़कर लपेट सकें यदि यह आपके लिए समझ में आता है ठोस समस्या (इस उत्तर के अंत में cf)।

अब क्या होता है यदि आप त्रुटि को बिल्कुल भी नहीं संभालते हैं: मान लें कि आपका class कथन मॉड्यूल के शीर्ष स्तर पर है (फ़ंक्शन में घोंसला नहीं है), अपवाद तब आग लग जाएगा जब रनटाइम स्क्रिप्ट या मॉड्यूल को निष्पादित करता है जिसमें शामिल है वर्ग परिभाषा। यदि युक्त फ़ाइल को मॉड्यूल के रूप में उपयोग किया जाता है (=> किसी अन्य स्थान से आयात किया जाता है) - जो सबसे अधिक संभावना है - यह मॉड्यूल के पहले आयात पर होगा, पायथन रनटाइम द्वारा पकड़ा जाएगा, और एक आयात त्रुटि द्वारा प्रतिस्थापित किया जाएगा, ताकि आप आयात कोड से मामले को ठीक से संभालने में सक्षम नहीं होगा।

स्पष्ट रूप से यहां सबसे अच्छा समाधान यहां कोई अपवाद होने से बचने के लिए है, और यदि आप इससे बच नहीं सकते हैं तो सुनिश्चित करें कि आप क्लास स्टेटमेंट के शरीर के भीतर से पूर्ण अपवाद (संदेश और ट्रेसबैक) लॉग करते हैं ताकि आपको संकेत मिले कि आयात क्यों विफल रहता है:

import logging
logger = logging.getLogger(__name__)

class Foo(object):
    try:
        myconst = some_func_that_raises()
    except Exception as e:
        logger.exception("failed to initialize Foo.my_const : %s", e)
        # let's not pretend otherwise : something failed and we cannot
        # fix it here
        raise    

अब वास्तविक प्रश्न हैं: क्यों यह फ़ंक्शन उठाता है, क्या आप इस अपवाद से ठीक से ठीक हो सकते हैं (इस तरह से क्लाइंट कोड को बाद में मेरा मतलब नहीं टूटेगा), और क्या आपको वास्तव में कॉल करने की आवश्यकता है यह इस बिंदु पर है? अपने मामले को ठीक से कैसे संभालना है यह वास्तव में उन बिंदुओं पर निर्भर करता है

1
bruno desthuilliers 27 मार्च 2018, 11:52

मैं इसे इस तरह से करूँगा, उस कोड को कम करना जो कोशिश के अंदर अपवाद फेंक सकता है - ब्लॉक को छोड़कर।

def throw_exception():
    raise Exception('exc')

class Foo(object):
    try:
        x = throw_exception()
    except Exception as exc:
        x = 'Exception was thrown: {}'.format(exc)

>>> Foo.x
'Exception was thrown: exc'

यह कोड हमेशा वर्ग बनाएगा, और चर मान फ़ंक्शन पर निर्भर करता है। यदि कोई अपवाद होता है, तो वह इसे कैप्चर करता है और मान को संपादित करता है।

1
Chen A. 27 मार्च 2018, 11:34

हाँ यह संभव है। कोशिश-छोड़कर बयानों के साथ बस वर्ग परिभाषा को लपेटें:

def some_func():
    raise Exception('some exception')

try:
    class X:
        y = some_func()
except Exception as e:
    print 'Got it!', e

प्रिंट के ऊपर दिए गए कोड को निष्पादित करना:

Got it! some exception
1
krassowski 27 मार्च 2018, 11:06