आधुनिक पायथन में कस्टम अपवाद घोषित करने का उचित तरीका?


1288

आधुनिक पायथन में कस्टम अपवाद कक्षाओं की घोषणा करने का उचित तरीका क्या है? मेरा प्राथमिक लक्ष्य यह है कि जो भी अन्य मानक अपवाद कक्षाएं हैं उनका पालन करें, ताकि (उदाहरण के लिए) मैं अपवाद में शामिल किसी भी अतिरिक्त स्ट्रिंग को उस टूल द्वारा अपवाद के रूप में प्रिंट किया गया हो।

"आधुनिक पायथन" से मेरा मतलब कुछ ऐसा है जो पायथन 2.5 में चलेगा, लेकिन पायथन 2.6 और पायथन के लिए 'सही' होगा 3. चीजों को करने का तरीका। और "कस्टम" से मेरा मतलब एक अपवाद वस्तु है जिसमें त्रुटि के कारण के बारे में अतिरिक्त डेटा शामिल हो सकते हैं: एक स्ट्रिंग, शायद अपवाद के लिए प्रासंगिक कुछ अन्य मनमानी वस्तु भी।

मैं पायथन 2.6.2 में निम्नलिखित पदावनति की चेतावनी के कारण फंस गया था:

>>> class MyError(Exception):
...     def __init__(self, message):
...         self.message = message
... 
>>> MyError("foo")
_sandbox.py:3: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6

यह पागल लगता है BaseExceptionजिसका नाम विशेषताओं के लिए एक विशेष अर्थ है message। मैं PEP-352 से इकट्ठा करता हूं कि विशेषता का 2.5 में एक विशेष अर्थ था जो वे दूर करने की कोशिश कर रहे हैं, इसलिए मुझे लगता है कि नाम (और वह अकेला) अब मना है? ओह।

मैं भी इस बात से वाकिफ हूं कि Exceptionकुछ मैजिक पैरामीटर हैं args, लेकिन मैं कभी नहीं जानता कि इसका उपयोग कैसे किया जाए। न ही मुझे यकीन है कि यह आगे बढ़ने वाली चीजों को करने का सही तरीका है; बहुत सारी चर्चा मुझे ऑनलाइन मिली जिसमें उन्होंने सुझाव दिया कि वे पायथन 3 में आर्गन्स के साथ दूर करने की कोशिश कर रहे हैं।

अद्यतन: दो उत्तर ने ओवरराइडिंग का सुझाव दिया है __init__, और __str__/ __unicode__/ __repr__। यह बहुत टाइपिंग की तरह लगता है, क्या यह आवश्यक है?

जवाबों:


1321

शायद मैं इस सवाल से चूक गया, लेकिन क्यों नहीं:

class MyException(Exception):
    pass

संपादित करें: कुछ को ओवरराइड करने के लिए (या अतिरिक्त आर्गन्स पास करें), ऐसा करें:

class ValidationError(Exception):
    def __init__(self, message, errors):

        # Call the base class constructor with the parameters it needs
        super(ValidationError, self).__init__(message)

        # Now for your custom code...
        self.errors = errors

इस तरह से आप त्रुटि संदेश के दूसरे पैरामाम को पास कर सकते हैं, और बाद में इसे प्राप्त कर सकते हैं e.errors


पायथन 3 अपडेट: पायथन 3+ में, आप इसका थोड़ा और अधिक कॉम्पैक्ट उपयोग कर सकते हैं super():

class ValidationError(Exception):
    def __init__(self, message, errors):

        # Call the base class constructor with the parameters it needs
        super().__init__(message)

        # Now for your custom code...
        self.errors = errors

35
हालाँकि इस तरह परिभाषित एक अपवाद नहीं होगा; यहाँ चर्चा देखें stackoverflow.com/questions/16244923/…
jiakai

86
@ मज़ाकई का अर्थ है "पिकलेबल"। :-)
रोबिनो

1
उपयोगकर्ता द्वारा परिभाषित अपवादों के लिए अजगर के प्रलेखन के बाद, जिन नामों का उल्लेख __init__ फ़ंक्शन में किया गया है, वे गलत हैं। इसके बजाय (स्व, संदेश, त्रुटि) यह (स्वयं, अभिव्यक्ति, संदेश) है। विशेषता अभिव्यक्ति इनपुट अभिव्यक्ति है जिसमें त्रुटि हुई और संदेश त्रुटि का स्पष्टीकरण है।
ddleon

1
यह एक गलतफहमी है, @ddleon। डॉक्स में आप जिस उदाहरण का उल्लेख कर रहे हैं वह किसी विशेष उपयोग के मामले के लिए है। उपवर्ग के निर्माता के तर्कों के नाम का कोई महत्व नहीं है (न ही उनकी संख्या)।
अष्टमेश

498

आधुनिक पायथन अपवादों के साथ, आपको दुरुपयोग .messageया ओवरराइड .__str__()या .__repr__()इसके किसी भी हिस्से की आवश्यकता नहीं है। यदि आप चाहते हैं कि आपके अपवाद के उठने पर एक सूचनात्मक संदेश हो, तो यह करें:

class MyException(Exception):
    pass

raise MyException("My hovercraft is full of eels")

इससे ट्रेसबैक समाप्त होगा MyException: My hovercraft is full of eels

यदि आप अपवाद से अधिक लचीलापन चाहते हैं, तो आप एक शब्दकोश को तर्क के रूप में पारित कर सकते हैं:

raise MyException({"message":"My hovercraft is full of animals", "animal":"eels"})

हालांकि, एक exceptब्लॉक में उन विवरणों को प्राप्त करने के लिए थोड़ा अधिक जटिल है। विवरण argsविशेषता में संग्रहीत हैं , जो एक सूची है। आपको ऐसा कुछ करने की आवश्यकता होगी:

try:
    raise MyException({"message":"My hovercraft is full of animals", "animal":"eels"})
except MyException as e:
    details = e.args[0]
    print(details["animal"])

अपवाद के लिए कई वस्तुओं को पास करना और उन्हें टपल इंडेक्स के माध्यम से एक्सेस करना अभी भी संभव है, लेकिन यह बहुत हतोत्साहित किया गया है (और थोड़ी देर पहले पदावनति के लिए भी इरादा था)। यदि आपको जानकारी के एक से अधिक टुकड़े की आवश्यकता है और उपरोक्त विधि आपके लिए पर्याप्त नहीं है, तो आपको ट्यूटोरियलException में वर्णित के रूप में उपवर्ग करना चाहिए ।

class MyError(Exception):
    def __init__(self, message, animal):
        self.message = message
        self.animal = animal
    def __str__(self):
        return self.message

2
"लेकिन यह भविष्य में पदावनत हो जाएगा" - क्या यह अभी भी पदावनति के लिए अभिप्रेत है? पायथन 3.7 अभी भी खुशी से स्वीकार करने लगता है Exception(foo, bar, qux)
mtraceur

संक्रमण के दर्द के कारण पिछले प्रयास में विफल होने के बाद से इसे हटाने के लिए हाल के किसी भी काम को नहीं देखा है, लेकिन यह उपयोग अभी भी हतोत्साहित है। मैं अपने उत्तर को प्रतिबिंबित करने के लिए अपडेट करूंगा।
frnknstn

@frnknstn, इसे हतोत्साहित क्यों किया जाता है? मेरे लिए एक अच्छा मुहावरा लगता है।
नेवेस

2
@ शुरुआत के लिए, अपवादों को संग्रहीत करने के लिए ट्यूपल्स का उपयोग करने से ऐसा करने के लिए शब्दकोश का उपयोग करने पर कोई लाभ नहीं होता है। यदि आप अपवाद परिवर्तनों के पीछे तर्क में रुचि रखते हैं, तो PEP352
frnknstn

PEP352 का प्रासंगिक अनुभाग "वापस लिया गया विचार" है
16:17 बजे

196

"आधुनिक पायथन में कस्टम अपवाद घोषित करने का उचित तरीका?"

यह ठीक है, जब तक कि आपका अपवाद वास्तव में अधिक विशिष्ट अपवाद का एक प्रकार न हो:

class MyException(Exception):
    pass

या बेहतर (शायद एकदम सही), passडॉकस्ट्रिंग देने के बजाय :

class MyException(Exception):
    """Raise for my specific kind of exception"""

सबक्लासिंग अपवाद उपवर्ग

से डॉक्स

Exception

सभी अंतर्निहित, गैर-सिस्टम-एक्साइटिंग अपवाद इस वर्ग से प्राप्त होते हैं। सभी उपयोगकर्ता-परिभाषित अपवाद भी इसी वर्ग से प्राप्त होने चाहिए।

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

class MyAppValueError(ValueError):
    '''Raise when my specific value is wrong'''

सेट विशेषताएँ आप एक कस्टम के साथ खुद को बनाते हैं __init__। एक तानाशाही तर्क के रूप में पारित करने से बचें, आपके कोड के भविष्य के उपयोगकर्ता आपको धन्यवाद देंगे। यदि आप पदावनत संदेश विशेषता का उपयोग करते हैं, तो इसे स्वयं निर्दिष्ट करने से आप बच जाएंगे DeprecationWarning:

class MyAppValueError(ValueError):
    '''Raise when a specific subset of values in context of app is wrong'''
    def __init__(self, message, foo, *args):
        self.message = message # without this you may get DeprecationWarning
        # Special attribute you desire with your Error, 
        # perhaps the value that caused the error?:
        self.foo = foo         
        # allow users initialize misc. arguments as any other builtin Error
        super(MyAppValueError, self).__init__(message, foo, *args) 

वास्तव में अपनी खुद की __str__या लिखने की कोई आवश्यकता नहीं है __repr__। बिल्टइन बहुत अच्छे हैं, और आपकी सहकारी विरासत सुनिश्चित करती है कि आप इसका उपयोग करते हैं।

शीर्ष उत्तर का आलोचक

शायद मैं इस सवाल से चूक गया, लेकिन क्यों नहीं:

class MyException(Exception):
    pass

फिर, ऊपर के साथ समस्या यह है कि इसे पकड़ने के लिए, आपको या तो इसे विशेष रूप से नाम देना होगा (यदि इसे कहीं और बनाया गया है) और आपको केवल उन अपवादों को पकड़ना चाहिए जिन्हें आप संभालने के लिए तैयार हैं)। इसी तरह की आलोचना नीचे करने के लिए है, लेकिन इसके अलावा इसके माध्यम से शुरू करने का तरीका नहीं है super, और DeprecationWarningयदि आप संदेश विशेषता का उपयोग करते हैं , तो आपको मिलेगा :

संपादित करें: कुछ को ओवरराइड करने के लिए (या अतिरिक्त आर्गन्स पास करें), ऐसा करें:

class ValidationError(Exception):
    def __init__(self, message, errors):

        # Call the base class constructor with the parameters it needs
        super(ValidationError, self).__init__(message)

        # Now for your custom code...
        self.errors = errors

इस तरह से आप त्रुटि संदेश के दूसरे पैरामाम को पास कर सकते हैं, और इसे बाद में ई.ओर्स के साथ प्राप्त कर सकते हैं

इसमें (दो तरफ से self) पास होने के लिए वास्तव में दो तर्कों की आवश्यकता होती है । यह एक दिलचस्प बाधा है कि भविष्य के उपयोगकर्ता सराहना नहीं कर सकते हैं।

प्रत्यक्ष होने के लिए - यह लिस्कोव प्रतिस्थापन क्षमता का उल्लंघन करता है ।

मैं दोनों त्रुटियों को प्रदर्शित करूँगा:

>>> ValidationError('foo', 'bar', 'baz').message

Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    ValidationError('foo', 'bar', 'baz').message
TypeError: __init__() takes exactly 3 arguments (4 given)

>>> ValidationError('foo', 'bar').message
__main__:1: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
'foo'

की तुलना में:

>>> MyAppValueError('foo', 'FOO', 'bar').message
'foo'

2
2018 से नमस्कार! BaseException.messageपायथन 3 में चला गया है, तो समालोचना केवल पुराने संस्करणों के लिए ही सही है?
कोस

5
@Kos Liskov सबस्टिबिलिटी के बारे में आलोचना अभी भी मान्य है। "संदेश" के रूप में पहले तर्क के शब्दार्थ भी यकीनन संदिग्ध हैं, लेकिन मुझे नहीं लगता कि मैं इस बात पर बहस करूंगा। जब मुझे अधिक खाली समय मिलेगा तो मैं इसे और अधिक रूप दूंगा।
हारून हॉल

1
एफडब्ल्यूआईडब्ल्यू, पायथन 3 के लिए (कम से कम 3.6+ के लिए), कोई व्यक्ति विशेषता पर निर्भर होने __str__के MyAppValueErrorबजाय विधि को फिर से परिभाषित करेगाmessage
जैक्वॉट

1
@AaronHall क्या आप एक्सेप्शन के बजाय सब-क्लासिंग वैल्यूएयर के लाभ पर विस्तार कर सकते हैं? आप कहते हैं कि डॉक्स का मतलब यही है, लेकिन एक प्रत्यक्ष रीडिंग उस व्याख्या का समर्थन नहीं करता है और उपयोगकर्ता द्वारा परिभाषित अपवादों के तहत पायथन ट्यूटोरियल में यह स्पष्ट रूप से उपयोगकर्ताओं को पसंद करता है: "अपवाद आमतौर पर अपवाद वर्ग से लिया जाना चाहिए, प्रत्यक्ष या अप्रत्यक्ष रूप से। ” इसलिए यह समझने की उत्सुकता है कि क्या आपका दृष्टिकोण उचित है, कृपया।
13

1
@ostergaard अभी पूर्ण उत्तर नहीं दे सकता है, लेकिन संक्षेप में, उपयोगकर्ता को पकड़ने का अतिरिक्त विकल्प मिलता है ValueError। यह समझ में आता है कि क्या यह मूल्य त्रुटियों की श्रेणी में है। यदि यह मान त्रुटियों की श्रेणी में नहीं है, तो मैं इसके खिलाफ शब्दार्थ पर बहस करूँगा। प्रोग्रामर की ओर से कुछ बारीकियों और तर्क के लिए जगह है, लेकिन मैं लागू होने पर विशिष्टता पसंद करता हूं। मैं जल्द ही इस विषय से बेहतर तरीके से निपटने के लिए अपने उत्तर को जल्द ही अपडेट करूंगा।
हारून हॉल

50

देखते हैं कि कैसे अपवाद डिफ़ॉल्ट रूप से काम करता है, तो एक बनाम अधिक गुण उपयोग किया जाता है (ट्रेस बैक छोड़े गए):

>>> raise Exception('bad thing happened')
Exception: bad thing happened

>>> raise Exception('bad thing happened', 'code is broken')
Exception: ('bad thing happened', 'code is broken')

इसलिए आप एक अपवाद के रूप में, एक अपवाद के रूप में, " अपवाद टेम्पलेट " का एक प्रकार होना चाह सकते हैं :

>>> nastyerr = NastyError('bad thing happened')
>>> raise nastyerr
NastyError: bad thing happened

>>> raise nastyerr()
NastyError: bad thing happened

>>> raise nastyerr('code is broken')
NastyError: ('bad thing happened', 'code is broken')

यह इस उपवर्ग के साथ आसानी से किया जा सकता है

class ExceptionTemplate(Exception):
    def __call__(self, *args):
        return self.__class__(*(self.args + args))
# ...
class NastyError(ExceptionTemplate): pass

और यदि आप उस डिफ़ॉल्ट टपल-जैसे प्रतिनिधित्व को पसंद नहीं करते हैं, __str__तो ExceptionTemplateकक्षा में विधि जोड़ें , जैसे:

    # ...
    def __str__(self):
        return ': '.join(self.args)

और आपके पास होगा

>>> raise nastyerr('code is broken')
NastyError: bad thing happened: code is broken

32

अजगर 3.8 (2018, https://docs.python.org/dev/whatsnew/3.8.html ) के अनुसार, अनुशंसित विधि अभी भी है:

class CustomExceptionName(Exception):
    """Exception raised when very uncommon things happen"""
    pass

कृपया दस्तावेज़ करना न भूलें, एक कस्टम अपवाद क्यों आवश्यक है!

यदि आप की जरूरत है, यह अधिक डेटा के साथ अपवादों के लिए जाने का तरीका है:

class CustomExceptionName(Exception):
    """Still an exception raised when uncommon things happen"""
    def __init__(self, message, payload=None):
        self.message = message
        self.payload = payload # you could add more args
    def __str__(self):
        return str(self.message) # __str__() obviously expects a string to be returned, so make sure not to send any other data types

और उन्हें लाइक करें:

try:
    raise CustomExceptionName("Very bad mistake.", "Forgot upgrading from Python 1")
except CustomExceptionName as error:
    print(str(error)) # Very bad mistake
    print("Detail: {}".format(error.payload)) # Detail: Forgot upgrading from Python 1

payload=Noneयह अचार बनाने में सक्षम है। इसे डंप करने से पहले, आपको कॉल करना होगा error.__reduce__()। लोडिंग उम्मीद के मुताबिक काम करेगी।

returnयदि आपको कुछ बाहरी संरचना में स्थानांतरित करने के लिए बहुत अधिक डेटा की आवश्यकता है, तो शायद आपको अजगर के बयान का उपयोग करके समाधान खोजने में जांच करनी चाहिए । यह मुझे स्पष्ट / अधिक स्पष्ट लगता है। उन्नत अपवाद जावा में भारी रूप से उपयोग किए जाते हैं, जो कभी-कभी कष्टप्रद हो सकते हैं, जब एक रूपरेखा का उपयोग करते हुए और सभी संभावित त्रुटियों को पकड़ने के लिए।


1
बहुत कम से कम, वर्तमान डॉक्स यह इंगित करते हैं कि यह ऐसा करने का तरीका है (कम से कम बिना __str__) के अन्य उत्तरों के बजाय जो उपयोग करते हैं super().__init__(...).. बस एक शर्म की बात है जिसके लिए ओवरराइड होता है __str__और __repr__शायद बेहतर "डिफ़ॉल्ट" क्रमांकन के लिए आवश्यक है।
केवलर

2
ईमानदार सवाल: अचार के योग्य होने के लिए अपवाद क्यों महत्वपूर्ण है? डंपिंग और लोडिंग अपवादों के लिए उपयोग के मामले क्या हैं?
Roel Schroeven

1
@RoelSchroeven: मुझे एक बार कोड को समानांतर करना था। Ran ठीक एकल प्रक्रिया, लेकिन इसके कुछ वर्गों के पहलू क्रमिक नहीं थे (लैम्बडा फ़ंक्शन को ऑब्जेक्ट के रूप में पारित किया जा रहा है)। मुझे कुछ समय लगा और इसे ठीक कर दिया। मतलब कोई व्यक्ति बाद में आपके कोड को क्रमबद्ध होने की आवश्यकता को समाप्त कर सकता है, ऐसा करने में असमर्थ हो सकता है, और यह खोदना होगा कि क्यों ... मेरा मुद्दा अनपेक्षित त्रुटियों का नहीं था, लेकिन मैं इसे समान समस्याओं के कारण देख सकता हूं।
लॉजिकऑब्स्ट्रक्शन

17

आपको संदेश का उपयोग करने के बजाय ओवरराइड __repr__या __unicode__तरीकों को छोड़ना चाहिए , जब आप अपवाद का निर्माण करते हैं तो आप argsअपवाद ऑब्जेक्ट की विशेषता में होंगे।


7

नहीं, "संदेश" निषिद्ध नहीं है। यह सिर्फ पदावनत है। आप संदेश का उपयोग करके ठीक काम करेंगे। लेकिन आप डिप्रैशन एरर से छुटकारा पाना चाह सकते हैं, बेशक।

जब आप अपने एप्लिकेशन के लिए कस्टम एक्सेप्शन क्लासेस बनाते हैं, तो उनमें से कई एक्सेप्शन से ही नहीं, बल्कि दूसरों से, जैसे कि वैल्यूएयर या इसी तरह के सबक्लास बनाते हैं। फिर आपको चर के उनके उपयोग के अनुकूल होना होगा।

और अगर आपके आवेदन में कई अपवाद हैं, तो यह आम तौर पर उन सभी के लिए एक सामान्य कस्टम बेस क्लास रखने का एक अच्छा विचार है, ताकि आपके मॉड्यूल के उपयोगकर्ता कर सकें

try:
    ...
except NelsonsExceptions:
    ...

और उस स्थिति में आप __init__ and __str__वहां आवश्यक कार्य कर सकते हैं , इसलिए आपको इसे हर अपवाद के लिए दोहराना नहीं है। लेकिन बस मैसेज वेरिएबल को कॉल करने के अलावा मैसेज के अलावा कुछ और ट्रिक करता है।

किसी भी मामले में, आपको केवल तभी आवश्यकता होती है __init__ or __str__जब आप अपवाद जो करते हैं उससे अलग कुछ करते हैं। और क्योंकि अगर डिप्रेसेशन है, तो आपको दोनों की आवश्यकता है, या आपको एक त्रुटि मिलती है। यह एक अतिरिक्त कोड की एक पूरी बहुत कुछ नहीं है जो आपको प्रति वर्ग की आवश्यकता है। ;)


यह दिलचस्प है कि Django अपवाद एक सामान्य आधार से विरासत में नहीं मिलता है। docs.djangoproject.com/en/2.2/_modules/django/core/exception क्या आपके पास एक अच्छा उदाहरण है जब किसी विशिष्ट एप्लिकेशन से सभी अपवादों को पकड़ना आवश्यक है? (शायद यह केवल कुछ विशिष्ट प्रकार के अनुप्रयोगों के लिए उपयोगी है)।
यारोस्लाव निकितेंको

मुझे इस विषय पर एक अच्छा लेख मिला, julien.danjou.info/python-exception-guide । मुझे लगता है कि अपवादों को मुख्य रूप से डोमेन-आधारित माना जाना चाहिए, न कि एप्लिकेशन-आधारित। जब आपका ऐप HTTP प्रोटोकॉल के बारे में है, तो आप HTTPError से प्राप्त करते हैं। जब आपके ऐप का हिस्सा टीसीपी है, तो आप उस हिस्से के अपवादों को TCPError से प्राप्त करते हैं। लेकिन अगर आपका ऐप बहुत सारे डोमेन (फ़ाइल, अनुमतियां, आदि) फैलाता है, तो MyBaseException कम होने का कारण कम हो जाता है। या यह 'परत उल्लंघन' से बचाने के लिए है?
यारोस्लाव निकितेंको

6

एक बहुत अच्छा लेख देखें " पायथन अपवादों के लिए निश्चित मार्गदर्शिका "। मूल सिद्धांत हैं:

  • हमेशा (कम से कम) अपवाद से विरासत में मिला।
  • हमेशा BaseException.__init__केवल एक तर्क के साथ कॉल करें ।
  • लाइब्रेरी बनाते समय, अपवाद से विरासत में मिली बेस क्लास को परिभाषित करें।
  • त्रुटि के बारे में विवरण दें।
  • अंतर्निहित अपवाद से प्रकार इनहेरिट जब यह समझ में आता है।

आयोजन (मॉड्यूल में) और अपवादों को लपेटने पर भी जानकारी है, मैं गाइड को पढ़ने की सलाह देता हूं।


1
यह एक अच्छा उदाहरण है कि क्यों एसओ पर मैं आमतौर पर सबसे अधिक उत्तोलित उत्तर की जांच करता हूं, लेकिन सबसे हाल ही में भी। उपयोगी जोड़, धन्यवाद।
लॉजिकऑब्स्ट्रक्शन 18

1
Always call BaseException.__init__ with only one argument.यह अनावश्यक तर्क की तरह लगता है, क्योंकि यह वास्तव में किसी भी तर्क को स्वीकार करता है।
यूजीन यर्मश

@EugeneYarmash मैं सहमत हूं, अब मुझे यह समझ में नहीं आता है। मैं वैसे भी इसका इस्तेमाल नहीं करता। शायद मुझे लेख को फिर से पढ़ना चाहिए और अपने उत्तर का विस्तार करना चाहिए।
यारोस्लाव निकितेंको

@EugeneYarmash मैंने फिर से लेख पढ़ा। यह कहा गया है कि कई तर्कों के मामले में C कार्यान्वयन कॉल "PyObject_Str (self-> args) लौटाता है"; इसका मतलब है कि एक स्ट्रिंग को कई लोगों की तुलना में बेहतर काम करना चाहिए। क्या आपने जांच की?
यारोस्लाव निकितेंको

3

इस उदाहरण का प्रयास करें

class InvalidInputError(Exception):
    def __init__(self, msg):
        self.msg = msg
    def __str__(self):
        return repr(self.msg)

inp = int(input("Enter a number between 1 to 10:"))
try:
    if type(inp) != int or inp not in list(range(1,11)):
        raise InvalidInputError
except InvalidInputError:
    print("Invalid input entered")

1

अपने स्वयं के अपवादों को सही ढंग से परिभाषित करने के लिए, कुछ सर्वोत्तम प्रथाएं हैं जिनका आपको पालन करने की आवश्यकता है:

  • से प्राप्त एक आधार वर्ग को परिभाषित करें Exception। यह परियोजना से संबंधित किसी भी अपवाद को पकड़ने की अनुमति देगा (अधिक विशिष्ट अपवादों को इससे प्राप्त होना चाहिए):

    class MyProjectError(Exception):
        """A base class for MyProject exceptions."""

    इन अपवाद वर्गों को एक अलग मॉड्यूल (जैसे exceptions.py) में व्यवस्थित करना आम तौर पर एक अच्छा विचार है।

  • अपने तर्क के लिए अतिरिक्त तर्क पास करने के लिए, __init__()चर संख्या के तर्कों के साथ एक कस्टम विधि परिभाषित करें । बेस क्लास की __init__()किसी भी स्थिति संबंधी दलीलों को पास करना (यह याद रखना कि BaseException/Exception किसी भी तरह की स्थिति संबंधी दलीलों की अपेक्षा करें ):

    class CustomError(MyProjectError):
        def __init__(self, *args, **kwargs):
            super(CustomError, self).__init__(*args)
            self.foo = kwargs.get('foo')

    एक अतिरिक्त तर्क के साथ इस तरह के अपवाद को बढ़ाने के लिए आप उपयोग कर सकते हैं:

    raise CustomError('Something bad happened', foo='foo')

    यह डिज़ाइन वास्तव में लिस्कोव प्रतिस्थापन सिद्धांत का पालन ​​करता है , क्योंकि आप एक व्युत्पन्न अपवाद वर्ग के एक उदाहरण के साथ एक आधार अपवाद वर्ग के एक उदाहरण को प्रतिस्थापित कर सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.