Answers:
පයිතන් හි ව්යතිරේකයක් මා අතින් විසි කරන්නේ කෙසේද?
ඔබේ ගැටලුවට අර්ථවත් ලෙස ගැලපෙන වඩාත් සුවිශේෂී ව්යතිරේක ඉදිකිරීම්කරු භාවිතා කරන්න .
ඔබේ පණිවිඩයේ නිශ්චිත වන්න, උදා:
raise ValueError('A very specific bad thing happened.')
සාමාන්යයක් මතු කිරීමෙන් වළකින්න Exception
. එය අල්ලා ගැනීම සඳහා, ඔබට එය උප පංතියේ වෙනත් විශේෂිත ව්යතිරේකයන් අල්ලා ගත යුතුය.
raise Exception('I know Python!') # Don't! If you catch, likely to hide bugs.
උදාහරණයක් වශයෙන්:
def demo_bad_catch():
try:
raise ValueError('Represents a hidden bug, do not catch this')
raise Exception('This is the exception you expect to handle')
except Exception as error:
print('Caught this error: ' + repr(error))
>>> demo_bad_catch()
Caught this error: ValueError('Represents a hidden bug, do not catch this',)
වඩාත් විශේෂිත ඇල්ලීම් සාමාන්ය ව්යතිරේකය අල්ලා නොගනී:
def demo_no_catch():
try:
raise Exception('general exceptions not caught by specific handling')
except ValueError as e:
print('we will not catch exception: Exception')
>>> demo_no_catch()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in demo_no_catch
Exception: general exceptions not caught by specific handling
raise
ප්රකාශයඒ වෙනුවට, ඔබේ ගැටලුවට අර්ථවත් ලෙස ගැලපෙන වඩාත් සුවිශේෂී ව්යතිරේක ඉදිකිරීම්කරු භාවිතා කරන්න .
raise ValueError('A very specific bad thing happened')
එමඟින් අත්තනෝමතික තර්ක ගණනක් ඉදිකිරීම්කරු වෙත ලබා දීමට ඉඩ දෙයි:
raise ValueError('A very specific bad thing happened', 'foo', 'bar', 'baz')
මෙම තර්ක වෙත ප්රවේශ args
වන්නේ Exception
වස්තුවෙහි ඇති ගුණාංගයෙනි. උදාහරණයක් වශයෙන්:
try:
some_code_that_may_raise_our_value_error()
except ValueError as err:
print(err.args)
මුද්රණ
('message', 'foo', 'bar', 'baz')
පයිතන් 2.5 හි, ව්යතිරේකයන් උප පංති සඳහා භාවිතා කරන්නන් දිරිගැන්වීම සහ භාවිතය නැවැත්වීම සඳහා සත්ය message
ගුණාංගයක් එකතු කරන BaseException
ලද args
නමුත් ආග්ස් හඳුන්වාදීම message
සහ මුල් අවලංගු කිරීම ඉවත් කර ඇත .
except
වගන්තියහැර වෙනත් වගන්තියක් තුළ සිටින විට, ඔබට යම් ආකාරයක දෝෂයක් සිදුවී ඇති බව සටහන් කර නැවත මතු කිරීමට අවශ්ය විය හැකිය. තොග හෝඩුවාව ආරක්ෂා කර ගනිමින් මෙය කළ හැකි හොඳම ක්රමය වන්නේ හිස් නැගීමේ ප්රකාශයක් භාවිතා කිරීමයි. උදාහරණයක් වශයෙන්:
logger = logging.getLogger(__name__)
try:
do_something_in_app_that_breaks_easily()
except AppError as error:
logger.error(error)
raise # just this!
# raise AppError # Don't do this, you'll lose the stack trace!
ඔබ සමඟ stacktrace (සහ දෝෂ අගය) ආරක්ෂා කළ හැකි sys.exc_info()
, නමුත් මෙම වැඩි දෝෂ ඇතිවීමට ඉඩ ඇති මාර්ගය සහ Python 2 සහ 3 අතර ගැළපුම පිළිබඳ ගැටළු ඇති , හිස් භාවිතා කිරීමට කැමති raise
නැවත මතු කිරීමට ය.
පැහැදිලි කිරීම සඳහා - sys.exc_info()
වර්ගය, අගය සහ ලුහුබැඳීම් ආපසු ලබා දෙයි.
type, value, traceback = sys.exc_info()
පයිතන් 2 හි ඇති වාක්ය ඛණ්ඩය මෙයයි - මෙය පයිතන් 3 සමඟ නොගැලපෙන බව සලකන්න:
raise AppError, error, sys.exc_info()[2] # avoid this.
# Equivalently, as error *is* the second object:
raise sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]
ඔබට අවශ්ය නම්, ඔබගේ නව නැගීම සමඟ සිදුවන්නේ කුමක්ද යන්න ඔබට වෙනස් කළ හැකිය - උදා args
: උදාහරණයක් ලෙස නව සැකසුම :
def error():
raise ValueError('oops!')
def catch_error_modify_message():
try:
error()
except ValueError:
error_type, error_instance, traceback = sys.exc_info()
error_instance.args = (error_instance.args[0] + ' <modification>',)
raise error_type, error_instance, traceback
තවද අපි ආග්ස් වෙනස් කරන අතරම සම්පූර්ණ ලුහුබැඳීම ආරක්ෂා කර ඇත්තෙමු. මෙය හොඳම භාවිතයක් නොවන අතර එය පයිතන් 3 හි වලංගු නොවන වාක්ය ඛණ්ඩයක් බව සලකන්න .
>>> catch_error_modify_message()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in catch_error_modify_message
File "<stdin>", line 2, in error
ValueError: oops! <modification>
දී Python 3 :
raise error.with_traceback(sys.exc_info()[2])
නැවතත්: ලුහුබැඳීම් අතින් හැසිරවීමෙන් වළකින්න. එය අඩු කාර්යක්ෂමතාවයක් සහ දෝෂ සහිත වේ. ඔබ නූල් භාවිතා කරන්නේ නම් සහ sys.exc_info
ඔබට වැරදි ලුහුබැඳීමක් පවා ලැබෙනු ඇත (විශේෂයෙන් ඔබ පාලක ප්රවාහය සඳහා ව්යතිරේක හැසිරවීමක් භාවිතා කරන්නේ නම් - මම පෞද්ගලිකව වැළකී සිටිමි.)
පයිතන් 3 හි, ඔබට ව්යතිරේකයන් දාම කළ හැකිය, එමඟින් ලුහුබැඳීම් ආරක්ෂා වේ:
raise RuntimeError('specific message') from error
පරීක්ෂාකාරී වන්න:
මේවා පහසුවෙන් සැඟවිය හැකි අතර නිෂ්පාදන කේතයට පවා ඇතුල් විය හැකිය. ඔබට ව්යතිරේකයක් මතු කිරීමට අවශ්ය වන අතර, ඒවා කිරීමෙන් ව්යතිරේකයක් මතු වනු ඇත, නමුත් අදහස් කළ දෙය නොවේ!
පයිතන් 2 හි වලංගු වේ, නමුත් පයිතන් 3 හි පහත සඳහන් නොවේ:
raise ValueError, 'message' # Don't do this, it's deprecated!
වලංගු වන්නේ පයිතන්හි (2.4 සහ පහළ) පැරණි අනුවාද වල පමණි , මිනිසුන් තවමත් නූල් ඔසවන බව ඔබට පෙනෙනු ඇත:
raise 'message' # really really wrong. don't do this.
සියලුම නවීන සංස්කරණ වලදී, මෙය ඇත්ත වශයෙන්ම a මතු කරයි TypeError
, මන්ද ඔබ BaseException
වර්ගයක් මතු නොකරන බැවිනි . ඔබ නිවැරදි ව්යතිරේකයක් සඳහා පරික්ෂා නොකරන්නේ නම් සහ ගැටලුව පිළිබඳව සමාලෝචකයෙකු නොමැති නම්, එය නිෂ්පාදනයට පිවිසිය හැකිය.
මගේ API වැරදියට භාවිතා කරන්නේ නම් පාරිභෝගිකයින්ට අනතුරු ඇඟවීම සඳහා මම ව්යතිරේක මතු කරමි:
def api_func(foo):
'''foo should be either 'baz' or 'bar'. returns something very useful.'''
if foo not in _ALLOWED_ARGS:
raise ValueError('{foo} wrong, use "baz" or "bar"'.format(foo=repr(foo)))
"මට අරමුණක් මත දෝෂයක් කිරීමට අවශ්යයි, එවිට එය හැරෙන්නට හැර යයි"
ඔබට ඔබේම දෝෂ වර්ග සෑදිය හැකිය, ඔබේ යෙදුමේ විශේෂිත යමක් වැරදියි කියා දැක්වීමට ඔබට අවශ්ය නම්, ව්යතිරේක ධූරාවලියෙහි සුදුසු ස්ථානය උපවර්ග කරන්න:
class MyAppLookupError(LookupError):
'''raise this when there's a lookup error for my app'''
සහ භාවිතය:
if important_key not in resource_dict and not ok_to_be_missing:
raise MyAppLookupError('resource is missing, and that is not ok.')
raise sys.exc_info()[0], (sys.exc_info()[1], my_extra_info), sys.exc_info()[2]
මට අවශ්ය දේ කරන බවක් පෙනේ, මම කිසි විටෙකත් ඒ සමඟ ගැටළු වලට මුහුණ දී නැත. නමුත් එය අනවසරයෙන් දැනෙනවා මිස පිළිගත් ක්රියාවක් නොවේ. මීට වඩා හොඳ ක්රමයක් තිබේද?
Exception
ඔබේ මව් පංතියෙන් ව්යුත්පන්න නොවන ව්යතිරේක 4 න් එකක් භාවිතා නොකළ යුතු බවයි - ඔබට වඩාත් විශේෂිත යමක් උපවර්ග කළ හැකි අතර එය අර්ථවත් නම් එසේ කළ යුතුය.
AppError
ව්යතිරේකයක් භාවිතා කරයි . බිල්ට් දෝෂයක් භාවිතා කිරීම වඩා හොඳ විය හැකියAttributeError
මෙය නොකරන්න . හිස් හදා වඩා
Exception
පරම වේ නොහැකි හරි දේ, ඒ වෙනුවට ආරොන් හෝල්ගේ විශිෂ්ට පිළිතුර බලන්න .
මෙයට වඩා වැඩි පයිතොනික් ලබා ගත නොහැක:
raise Exception("I know python!")
ඔබට තවත් තොරතුරු අවශ්ය නම් පයිතන් සඳහා ඉහළ නැංවීමේ ප්රකාශය බලන්න .
පයිතන් 3 හි ව්යතිරේකයන් සඳහා විවිධ සින්ටැක්ස් 4 ක් ඇත:
1. raise exception
2. raise exception (args)
3. raise
4. raise exception (args) from original_exception
1. ව්යතිරේකය එදිරිව එදිරිව. 2. ව්යතිරේකය ඉහළ නැංවීම (ආර්ග්)
ඔබ raise exception (args)
ව්යතිරේකයක් මතු කිරීමට භාවිතා කරන්නේ නම්, ඔබ args
ව්යතිරේක වස්තුව මුද්රණය කරන විට මුද්රණය කෙරේ - පහත උදාහරණයේ පෙන්වා ඇති පරිදි.
#raise exception (args)
try:
raise ValueError("I have raised an Exception")
except ValueError as exp:
print ("Error", exp) # Output -> Error I have raised an Exception
#raise execption
try:
raise ValueError
except ValueError as exp:
print ("Error", exp) # Output -> Error
3.රයිස්
raise
කිසිදු තර්කයකින් තොරව ප්රකාශය අවසාන ව්යතිරේකය නැවත මතු කරයි. ව්යතිරේකය අල්ලා ගැනීමෙන් පසු ඔබට යම් ක්රියාමාර්ගයක් ගැනීමට අවශ්ය නම් එය නැවත ඉහළ නැංවීමට අවශ්ය නම් මෙය ප්රයෝජනවත් වේ. නමුත් මීට පෙර ව්යතිරේකයක් නොතිබුනේ නම්, raise
ප්රකාශය TypeError
ව්යතිරේකය මතු කරයි .
def somefunction():
print("some cleaning")
a=10
b=0
result=None
try:
result=a/b
print(result)
except Exception: #Output ->
somefunction() #some cleaning
raise #Traceback (most recent call last):
#File "python", line 8, in <module>
#ZeroDivisionError: division by zero
4. ඔරිජිනල්_එක්සෙප්ෂන් වෙතින් ව්යතිරේකය (ආර්ග්) මතු කරන්න
මෙම ප්රකාශය ව්යතිරේක දාමයක් නිර්මාණය කිරීම සඳහා භාවිතා කරනු ලබන අතර, වෙනත් ව්යතිරේකයකට ප්රතිචාර වශයෙන් මතු කරන ලද ව්යතිරේකයක මුල් ව්යතිරේකයේ විස්තර අඩංගු විය හැකිය - පහත උදාහරණයේ පෙන්වා ඇති පරිදි.
class MyCustomException(Exception):
pass
a=10
b=0
reuslt=None
try:
try:
result=a/b
except ZeroDivisionError as exp:
print("ZeroDivisionError -- ",exp)
raise MyCustomException("Zero Division ") from exp
except MyCustomException as exp:
print("MyException",exp)
print(exp.__cause__)
ප්රතිදානය:
ZeroDivisionError -- division by zero
MyException Zero Division
division by zero
exception(args)
කටexception (args)
raise exception(args) from None
දැනට ක්රියාකාරී හැර කටයුතු හා තවදුරටත් වැඩි උනන්දුවක් දක්වනු ලබන බව කියන්න. එසේ නොමැතිනම් ඔබ වාරණයක් තුළ ව්යතිරේකයක් මතු කර except
එය හසුරුවන්නේ නැත්නම්, “ඉහත ව්යතිරේකය හැසිරවීමේදී තවත් ව්යතිරේකයක් සිදුවිය” යන
සමහර අනපේක්ෂිත තත්වයන්ට ප්රතිචාර වශයෙන් ඔබ ව්යතිරේකයක් විසි කළ යුතු පොදු අවස්ථාව සඳහා, සහ ඔබ කිසි විටෙකත් අල්ලා ගැනීමට අදහස් නොකරන නමුත්, එය සිදු වුවහොත් එතැන් සිට නිදොස් කිරීමට ඔබට හැකි වන පරිදි වේගයෙන් අසමත් වීම - වඩාත්ම තාර්කික එකක් ලෙස පෙනේ AssertionError
:
if 0 < distance <= RADIUS:
#Do something.
elif RADIUS < distance:
#Do something.
else:
raise AssertionError("Unexpected value of 'distance'!", distance)
ValueError
වඩා AssertionError
ප්රකාශයකින් සමග කිසිදු ගැටලුවක් (කිසිවක් මෙහිදී සිදු කොට ඇත නිසා) තියෙනවා නිසා - ගැටලුව වටිනාකම වේ. AssertionError
මෙම නඩුවේ ඔබට සැබවින්ම අවශ්ය නම් , ලියන්න assert distance > 0, 'Distance must be positive'
. නමුත් ඔබ ඒ ආකාරයෙන් දෝෂ පරීක්ෂා නොකළ යුතුය python -O
.
-O
.
දැනට පවතින පිළිතුරු පළමුව කියවන්න, මෙය අතිරේකයක් පමණි.
ඔබට තර්ක සමඟ හෝ නැතිව ව්යතිරේකයන් මතු කළ හැකි බව සලකන්න.
උදාහරණයක්:
raise SystemExit
වැඩසටහනෙන් ඉවත් වන නමුත් ඔබට සිදුවූයේ කුමක්දැයි දැන ගැනීමට අවශ්ය විය හැකිය.ඉතින් ඔබට මෙය භාවිතා කළ හැකිය.
raise SystemExit("program exited")
මෙය වැඩසටහන වසා දැමීමට පෙර stderr වෙත "වැඩසටහනෙන් පිටවීම" මුද්රණය කරයි.
raise SystemExit()
වඩා හොඳ තෝරා ගැනීමක් විය? පළමු එක පවා ක්රියාත්මක වන්නේ ඇයි?
ව්යතිරේකයක් විසි කිරීමට තවත් ක්රමයක් නම් assert
. කොන්දේසියක් සපුරා ඇත්දැයි තහවුරු කර ගැනීමට ඔබට තහවුරු කිරීම භාවිතා කළ හැකිය AssertionError
. වැඩි විස්තර සඳහා මෙහි බලන්න .
def avg(marks):
assert len(marks) != 0,"List is empty."
return sum(marks)/len(marks)
mark2 = [55,88,78,90,79]
print("Average of mark2:",avg(mark2))
mark1 = []
print("Average of mark1:",avg(mark1))
සටහන් කර ගැනීම සඳහා: ඔබට සාමාන්ය ව්යතිරේකයන් හැසිරවීමට අවශ්ය අවස්ථා තිබේ. ඔබ ලිපිගොනු පොකුරක් සකසමින් ඔබේ දෝෂ සටහන් කරන්නේ නම්, ගොනුවක් සඳහා සිදුවන ඕනෑම දෝෂයක් අල්ලා ගැනීමට, එය ලොග් කිරීමට සහ ඉතිරි ලිපිගොනු දිගටම සැකසීමට ඔබට අවශ්ය විය හැකිය. එවැනි අවස්ථාවක, අ
try:
foo()
except Exception as e:
print(str(e)) # Print out handled error
එය කිරීමට හොඳ ක්රමයක් අවහිර කරන්න. ඔබට තවමත් raise
නිශ්චිත ව්යතිරේකයන් කිරීමට අවශ්ය වනු ඇත, එවිට ඒවා අදහස් කරන්නේ කුමක්දැයි ඔබ දැන ගනු ඇත.
ඒ සඳහා පයිතන් නැංවීමේ ප්රකාශය ඔබ ඉගෙන ගත යුතුය. එය උත්සාහක කොටස තුළ තබා ගත යුතුය. උදාහරණයක් -
try:
raise TypeError #remove TypeError by any other error if you want
except TypeError:
print('TypeError raised')
raise
දෙය නම්, තොග හෝඩුවාව බිඳ නොගෙන කේත ක්රියාත්මක කිරීමේ විවිධ මට්ටම්වල අභිරුචි දෝෂ නිදොස් කිරීම සිදු කිරීමට මට අවශ්ය වූ දෙයයි.