නූතන පයිතන් හි අභිරුචි ව්‍යතිරේක ප්‍රකාශ කිරීමට නිසි ක්‍රමයක් තිබේද?


1317

නූතන පයිතන් හි අභිරුචි ව්‍යතිරේක පන්ති ප්‍රකාශ කිරීමට සුදුසුම ක්‍රමය කුමක්ද? මගේ මූලික ඉලක්කය වන්නේ වෙනත් ව්‍යතිරේක පංති ඇති ඕනෑම සම්මතයක් අනුගමනය කිරීමයි, එවිට (නිදසුනක් ලෙස) ව්‍යතිරේකයේ මා ඇතුළත් කරන ඕනෑම අමතර නූලක් ව්‍යතිරේකය අල්ලා ගත් ඕනෑම මෙවලමක් මඟින් මුද්‍රණය කරනු ලැබේ.

"නූතන පයිතන්" යන්නෙන් මා අදහස් කරන්නේ පයිතන් 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__. එය බොහෝ ටයිප් කිරීමක් සේ පෙනේ, එය අවශ්‍යද?


2
පයිතන් තමන්ගේම There should be one-- and preferably only one --obvious way to do it.
පුරාවෘත්තයක්

Answers:


1365

සමහර විට මට ප්‍රශ්නය මග හැරී ඇත, නමුත් ඇයි නැත්තේ:

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

36
කෙසේ වෙතත් මේ ආකාරයට අර්ථ දක්වා ඇති ව්‍යතිරේකයක් තෝරා ගත නොහැකි වනු ඇත; සාකච්ඡාව මෙතැනින් බලන්න stackoverflow.com/questions/16244923/…
jiakai

89
ජියාකායි යන්නෙහි තේරුම “අච්චාරු දැමිය හැකි” යන්නයි. :-)
රොබිනෝ

1
පරිශීලක අර්ථ දක්වන ලද ව්‍යතිරේක සඳහා පයිතන් ලේඛනගත කිරීමෙන් පසුව, __init__ ශ්‍රිතයේ සඳහන් කර ඇති නම් වැරදිය. (ස්වයං, පණිවිඩය, දෝෂය) වෙනුවට එය (ස්වයං, ප්‍රකාශනය, පණිවිඩය) වේ. ආරෝපණ ප්‍රකාශනය යනු දෝෂය සිදුවූ ආදාන ප්‍රකාශනය වන අතර පණිවිඩය දෝෂය පිළිබඳ පැහැදිලි කිරීමකි.
ddleon

3
එය වරදවා වටහා ගැනීමකි. ඔබ සඳහන් කරන ලියකියවිලි වල උදාහරණය විශේෂිත භාවිත අවස්ථාවක් සඳහා ය. උප පංතියේ ඉදිකිරීම්කරුවන්ගේ තර්කවල නමට කිසිදු වැදගත්කමක් නැත (හෝ ඒවායේ අංකය).
asthasr

512

නූතන පයිතන් ව්යතිරේක සමග, ඔබ අපචාරයට අවශ්ය නැහැ .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

rfrnknstn, එය අධෛර්යමත් වන්නේ ඇයි? මට හොඳ මෝඩකමක් වගේ.
neves

2
ආරම්භයක් සඳහා නවීස්, ව්‍යතිරේක තොරතුරු ගබඩා කිරීම සඳහා ටුපල් භාවිතා කිරීමෙන් ශබ්ද කෝෂයක් භාවිතා කිරීමෙන් වැඩි ප්‍රයෝජනයක් නොමැත. ව්‍යතිරේක වෙනස්වීම් පිටුපස ඇති තර්කනය ගැන ඔබ උනන්දුවක් දක්වන්නේ නම්, PEP352
frnknstn

PEP352 හි අදාළ කොටස වන්නේ " ආපසු ලබාගත් අදහස්" ය .
liberforce

198

"නූතන පයිතන් හි අභිරුචි ව්‍යතිරේක ප්‍රකාශ කිරීමට නිසි ක්‍රමයක් තිබේද?"

ඔබේ ව්‍යතිරේකය සැබවින්ම වඩා සුවිශේෂී ව්‍යතිරේක වර්ගයක් නොවේ නම් මෙය හොඳයි:

class MyException(Exception):
    pass

හෝ වඩා හොඳ (සමහර විට පරිපූර්ණ), passලේඛ ලේඛනයක් ලබා දෙනවා වෙනුවට :

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

උප පංති ව්‍යතිරේක උප පංති

සිට ලේඛන

Exception

සියලු සාදන ලද, පද්ධති නොවන පිටවීමේ ව්‍යතිරේකයන් මෙම පන්තියෙන් ව්‍යුත්පන්න කර ඇත. පරිශීලක අර්ථ දක්වන ලද සියලුම ව්‍යතිරේකයන් ද මෙම පන්තියෙන් ලබා ගත යුතුය.

මාර්ගයෙන් බව නම් ඔබේ හැර ඒ වෙනුවට Generic බලපත්රය යටතේ අවසර ලබා ඇත පිළිබඳ වඩාත් විශේෂිත හැර, උපපංතිය බව හැර වර්ගයකි 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

එමඟින් ඔබට දෙවන පරාමිතිය වෙත වැරදි පණිවිඩ යැවිය හැකි අතර පසුව එය e.errors සමඟ ලබා ගත හැකිය

ඒ සඳහා හරියටම තර්ක දෙකක් ඉදිරිපත් කිරීම අවශ්‍ය වේ self. එය අනාගත පරිශීලකයින් අගය නොකරන සිත්ගන්නා සුළු බාධකයකි.

සෘජු වීමට - එය ලිස්කොව් ආදේශන හැකියාව උල්ලං lates නය කරයි .

මම දෝෂ දෙකම නිරූපණය කරමි:

>>> 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
Os කොස් ලිස්කොව් ආදේශන හැකියාව පිළිබඳ විවේචනය තවමත් වලංගු වේ. "තර්කයක්" ලෙස පළමු තර්කයේ අර්ථ නිරූපණය ද සැක සහිත ය, නමුත් මම කාරණය තර්ක කරනු ඇතැයි මම නොසිතමි. මට වැඩි නිදහස් කාලයක් ඇති විට මම මෙය තවත් පෙනුමක් ලබා දෙන්නෙමි.
ආරොන් හෝල්

1
FWIW, පයිතන් 3 සඳහා (අවම වශයෙන් 3.6+ සඳහා), යමෙක් ගුණාංගය මත රඳා සිටීම වෙනුවට __str__ක්‍රමවේදය නැවත අර්ථ දක්වනු ඇතMyAppValueErrormessage
Jacquot

2
අභිරුචි ව්‍යතිරේකයන් සමඟ ලිස්කොව් ආදේශන මූලධර්මය අනුගමනය කිරීමේ වැඩි අර්ථයක් මට නොපෙනේ. නිශ්චිත තත්වයක් දැක්වීමට ඔබ විශේෂිත ව්‍යතිරේකයක් මතු කරයි. මූලික ව්‍යතිරේක පංතියක ව්‍යුත්පන්න ව්‍යතිරේක පංතියක උදාහරණයක් ආදේශ කිරීමට ඔබට කවදා හෝ අවශ්‍ය වන්නේ ඇයි?
ඉයුජින් යාමෂ්

2
A ආරොන්හෝල් මට මෙය කිසි විටෙකත් ප්‍රායෝගිකව අවශ්‍ය නොවීය. කෙසේ වෙතත්, ඔබගේ උදාහරණය එල්එස්පී ද උල්ලං lates නය කරන බව මම අනුමාන කරමි: ඔබේ කේතය භාවිතා කරන්නේ නම් raise ValueError(msg), ඔබට raise ValidationError(msg)තවත් එක් පරාමිතියක් අවශ්‍ය බැවින් මෙය ප්‍රතිස්ථාපනය කළ නොහැක .
ඉයුජින් යාමෂ්

51

තවත් ගුණාංග එදිරිව භාවිතා කරන්නේ නම් පෙරනිමියෙන් ව්‍යතිරේකයන් ක්‍රියා කරන්නේ කෙසේදැයි බලන්න (ලුහුබැඳීම් මඟ හැරී ඇත):

>>> 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

36

පයිතන් 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
ORoelSchroeven: මට එක් වරක් කේතය සමාන්තරගත කිරීමට සිදු විය. සිහින් තනි ක්‍රියාවලියක් පවත්වා ගෙන ගිය නමුත් එහි සමහර පංතිවල අනුක්‍රමික විය නොහැක (ලැම්බඩා ක්‍රියාකාරිත්වය වස්තු ලෙස සම්මත වේ). එය හදුනාගෙන එය නිවැරදි කිරීමට මට යම් කාලයක් ගත විය. පසුව යමෙකු අදහස් කරන්නේ ඔබේ කේතය අනුක්‍රමිකකරණය කිරීම, එය කිරීමට නොහැකි වීම සහ ඒ ඇයි දැයි සොයා බැලීම අවශ්‍ය විය හැකිය ... මගේ ගැටලුව හඳුනාගත නොහැකි දෝෂ නොවේ, නමුත් එය සමාන ගැටළු ඇති කරන බව මට පෙනේ.
logOnAbstractions

18

පණිවුඩය භාවිතා කිරීම වෙනුවට ඔබ අභිබවා යා යුතුය, __repr__නැතහොත් __unicode__ක්‍රමෝපායන් කළ යුතුය , ඔබ ව්‍යතිරේකය ගොඩනඟන විට ඔබ සපයන ආග්ස් argsව්‍යතිරේක වස්තුවෙහි ගුණාංගයේ ඇත.


8

නැත, "පණිවිඩය" තහනම් නොවේ. එය නිකම්ම අතහැර දමා ඇත. ඔබගේ යෙදුම පණිවිඩය භාවිතා කිරීම සමඟ හොඳින් ක්‍රියා කරයි. නමුත් ක්ෂය වීමේ දෝෂයෙන් මිදීමට ඔබට අවශ්‍ය විය හැකිය.

ඔබගේ යෙදුම සඳහා ඔබ අභිරුචි ව්‍යතිරේක පංති නිර්මාණය කරන විට, ඒවායින් බොහොමයක් ව්‍යතිරේකයෙන් පමණක් නොව, ValueError හෝ ඊට සමාන වෙනත් අයගෙන් උපවර්ගයක් නොවේ. එවිට ඔබ ඔවුන්ගේ විචල්යයන් භාවිතා කිරීමට අනුගත විය යුතුය.

ඔබේ යෙදුමේ ඔබට බොහෝ ව්‍යතිරේක තිබේ නම්, ඒ සියල්ල සඳහා පොදු අභිරුචි පාදක පන්තියක් තිබීම සාමාන්‍යයෙන් හොඳ අදහසකි, එවිට ඔබේ මොඩියුල භාවිතා කරන්නන්ට කළ හැකිය

try:
    ...
except NelsonsExceptions:
    ...

එවැනි අවස්ථාවකදී ඔබට __init__ and __str__අවශ්‍ය දේ එහි කළ හැකිය , එබැවින් සෑම ව්‍යතිරේකයක් සඳහාම එය නැවත කිරීමට අවශ්‍ය නැත. නමුත් පණිවිඩ විචල්‍යයට පණිවුඩයට වඩා වෙනත් දෙයක් ඇමතීම උපක්‍රමය කරයි.

කෙසේ වෙතත්, ඔබට අවශ්‍ය __init__ or __str__වන්නේ ඔබ විසින්ම ව්‍යතිරේකයට වඩා වෙනස් දෙයක් කළහොත් පමණි . ක්ෂයවීම නම්, ඔබට ඒ දෙකම අවශ්‍ය වේ, නැතහොත් ඔබට දෝෂයක් ඇති වේ. එය එක් පන්තියකට ඔබට අවශ්‍ය අමතර කේත රාශියක් නොවේ. ;)


ජැන්ගෝ ව්‍යතිරේකයන් පොදු පදනමකින් උරුම නොවීම සිත්ගන්නා කරුණකි. docs.djangoproject.com/en/2.2/_modules/django/core/exceptions නිශ්චිත යෙදුමකින් සියලු ව්‍යතිරේක අවශ්‍ය වන විට ඔබට හොඳ උදාහරණයක් තිබේද? (සමහර විට එය ප්‍රයෝජනවත් වන්නේ සමහර විශේෂිත යෙදුම් සඳහා පමණි).
යාරොස්ලාව් නිකිටෙන්කෝ

මෙම මාතෘකාව පිළිබඳ හොඳ ලිපියක් මට හමු විය, julien.danjou.info/python-exceptions-guide . ව්‍යතිරේකයන් මූලික වශයෙන් වසම් මත පදනම් වූවක් මිස යෙදුම් මත පදනම් වූවක් නොවන බව මම සිතමි. ඔබගේ යෙදුම HTTP ප්‍රොටෝකෝලය ගැන වන විට, ඔබ ව්‍යුත්පන්න කර ඇත්තේ HTTPError ය. ඔබගේ යෙදුමේ කොටසක් TCP වන විට, ඔබ එම කොටස TCPError වෙතින් ව්‍යුත්පන්න කර ඇත. නමුත් ඔබගේ යෙදුම බොහෝ වසම් (ගොනු, අවසර, ආදිය) දක්වා විහිදේ නම්, MyBaseException ඇති වීමට හේතුව අඩු වේ. නැතහොත් එය 'ස්ථර උල්ලං from නය කිරීම්' වලින් ආරක්ෂා කිරීමද?
යාරොස්ලාව් නිකිටෙන්කෝ

8

ඉතා හොඳ ලිපියක් බලන්න " පයිතන් ව්‍යතිරේකයන් සඳහා නියත මාර්ගෝපදේශය ". මූලික මූලධර්ම නම්:

  • සෑම විටම (අවම වශයෙන්) ව්‍යතිරේකයෙන් උරුම වන්න.
  • සෑම විටම BaseException.__init__එකම තර්කයක් සමඟ අමතන්න .
  • පුස්තකාලයක් තැනීමේදී, ව්‍යතිරේකයෙන් උරුම වන මූලික පන්තියක් අර්ථ දක්වන්න.
  • දෝෂය පිළිබඳ විස්තර සපයන්න.
  • අර්ථවත් වූ විට බිල්ඩින් ව්‍යතිරේක වර්ග වලින් උරුම වන්න.

සංවිධානය කිරීම (මොඩියුල වලින්) සහ එතීෙම් ව්‍යතිරේකයන් පිළිබඳ තොරතුරු ද ඇත, මාර්ගෝපදේශය කියවීමට මම නිර්දේශ කරමි.


1
SO හි මම සාමාන්‍යයෙන් වඩාත්ම උත්තරීතර පිළිතුර පරික්ෂා කරන්නේ ඇයිද යන්නට මෙය හොඳ උදාහරණයකි, නමුත් නවතම ඒවාද. ප්‍රයෝජනවත් එකතු කිරීම, ස්තූතියි.
logOnAbstractions

1
Always call BaseException.__init__ with only one argument.අනවශ්‍ය බාධකයක් ලෙස පෙනේ, මන්ද එය ඇත්ත වශයෙන්ම ඕනෑම තර්ක ගණනාවක් පිළිගන්නා බැවිනි.
ඉයුජින් යාමෂ්

Ug ඉයුජින් යර්මාෂ් මම එකඟයි, දැන් මට එය තේරෙන්නේ නැත. මම එය කෙසේ හෝ භාවිතා නොකරමි. සමහර විට මම ලිපිය නැවත කියවා මගේ පිළිතුර පුළුල් කළ යුතුයි.
යාරොස්ලාව් නිකිටෙන්කෝ

Ug ඉයුජින් යර්මාෂ් මම නැවත ලිපිය කියෙව්වා. තර්ක කිහිපයක් ඇති විට C ක්‍රියාත්මක කිරීම "ආපසු PyObject_Str (self-> args)" යනුවෙන් සඳහන් කර ඇත. එයින් අදහස් වන්නේ එක් නූල් කිහිපයකට වඩා හොඳින් ක්‍රියා කළ යුතු බවයි. ඔබ එය පරීක්ෂා කළාද?
යාරොස්ලාව් නිකිටෙන්කෝ

6

ඔබේම ව්‍යතිරේකයන් නිවැරදිව නිර්වචනය කිරීමට, ඔබ අනුගමනය කළ යුතු හොඳම භාවිතයන් කිහිපයක් තිබේ:

  • උරුම වන මූලික පන්තියක් නිර්වචනය කරන්න 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().__init__(*args)
            self.foo = kwargs.get('foo')

    එවැනි ව්‍යතිරේකයක් අතිරේක තර්කයක් සමඟ මතු කිරීමට ඔබට භාවිතා කළ හැකිය:

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

මෙම සැලසුම ලිස්කොව් ආදේශන මූලධර්මයට අනුකූල වේ , මන්ද ඔබට මූලික ව්‍යතිරේක පන්තියක නිදසුනක් ව්‍යුත්පන්න ව්‍යතිරේක පන්තියක ආදේශ කළ හැකිය. එසේම, මවුපියන්ට සමාන පරාමිතීන් සහිත ව්‍යුත්පන්න පන්තියක උදාහරණයක් නිර්මාණය කිරීමට එය ඔබට ඉඩ සලසයි.


2
ඇත්තටම මෙම සැලසුමට කැමතියි ... අනෙක් පිළිතුරු වලට වඩා එය පිරිසිදු බව මට හැඟේ.
ලූක් සේව්ෆ්‍රොග්ස්

එල්එස්පී මැලියම් අනිවාර්ය විය යුතුය, ඒ නිසා මම අනෙක් අයට මෙම පිළිතුරට කැමැත්තෙමි.
loutre

4

මෙම උදාහරණය උත්සාහ කරන්න

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")

0

ඇත්තෙන්ම සරල ප්‍රවේශයක්:

class CustomError(Exception):
    pass

raise CustomError("Hmm, seems like this was custom coded...")

නැතහොත්, මුද්‍රණයකින් තොරව දෝෂය මතු කර ගන්න __main__(පිරිසිදු හා පිළිවෙලට පෙනේ):

class CustomError(Exception):
    __module__ = Exception.__module__

raise CustomError("Improved CustomError!")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.