Hoe kan ik een uitzondering in Python verhogen, zodat het later kan worden gepakt via een except
BLOCK?
1, Autoriteit 100%
Hoe gooi ik handmatig een uitzondering in Python?
Gebruik de meest specifieke uitzonderingstructuur die semantisch past bij uw probleem .
Wees specifiek in uw bericht, b.v.:
raise ValueError('A very specific bad thing happened.')
Verhoog geen generieke uitzonderingen
Vermijd het verhogen van een generieke Exception
. Om het te vangen, moet je alle andere meer specifieke uitzonderingen vangen die het subclass.
Probleem 1: verbergingsbugs
raise Exception('I know Python!') # Don't! If you catch, likely to hide bugs.
Bijvoorbeeld:
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',)
Probleem 2: niet vangen
En meer specifieke vangsten zullen de algemene uitzondering niet vangen:
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
Beste praktijken: raise
Verklaring
raise ValueError('A very specific bad thing happened')
waardoor ook handig een willekeurig aantal argumenten worden doorgegeven aan de constructor:
raise ValueError('A very specific bad thing happened', 'foo', 'bar', 'baz')
Deze argumenten zijn toegankelijk via de args
ATRIBUTE op de Exception
Object. Bijvoorbeeld:
try:
some_code_that_may_raise_our_value_error()
except ValueError as err:
print(err.args)
PRINTS
('message', 'foo', 'bar', 'baz')
In Python 2.5, een daadwerkelijke message
Attribuut is toegevoegd aan BaseException
Ten gunste van het aanmoedigen van gebruikers om uitzonderingen te ondersteunen en te stoppen met het gebruik van args
, maar De introductie van message
en de oorspronkelijke afschrijving van Args is ingetrokken .
Beste praktijken: except
clausule
Als u zich in een uitzonderingsclausule bevindt, wilt u bijvoorbeeld registreren dat er een specifiek type fout is opgetreden en vervolgens opnieuw verhogen. De beste manier om dit te doen met behoud van de stacktracering, is door een bare raise-statement te gebruiken. Bijvoorbeeld:
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!
Wijzig uw fouten niet… maar als u erop staat.
Je kunt de stacktrace (en foutwaarde) behouden met sys.exc_info()
, maar dit is veel foutgevoeligeren heeft compatibiliteitsproblemen tussen Python 2 en 3, gebruik liever een kale raise
om te reraisen.
Om uit te leggen: de sys.exc_info()
retourneert het type, de waarde en de traceback.
type, value, traceback = sys.exc_info()
Dit is de syntaxis in Python 2 – let op: dit is niet compatibel met Python 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]
Als je wilt, kun je wijzigen wat er gebeurt met je nieuwe verhoging – b.v. nieuwe args
instellen voor de instantie:
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
en we hebben het hele traceerback bewaard terwijl we de args wijzigen. Merk op dat dit is niet een beste praktijk en het is ongeldige syntaxis in Python 3 (maak compatibiliteit veel moeilijker om rond te werken).
>>> 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>
in python 3 :
raise error.with_traceback(sys.exc_info()[2])
Nogmaals: vermijd handmatig manipuleren van traceerbacks. Het is minder efficiënt en meer foutgevoelig. En als u Dreiging en sys.exc_info
gebruikt, kunt u zelfs de verkeerde traceback krijgen (vooral als u een uitzonderingsafhandeling gebruikt voor de besturingsstroom – die persoonlijk de neiging heeft om te vermijden.)
Python 3, Uitzondering Chaining
In Python 3 kunt u uitzonderingen keten, die Tracebacks behouden:
raise RuntimeError('specific message') from error
Houd er rekening mee:
- Deze staat toe dat het fouttype wordt aangevoerd, en
- Dit is niet compatibel met Python 2.
verouderde methoden:
Deze kunnen gemakkelijk worden verborgen en zelfs in productiecode terechtkomen. U wilt een uitzondering maken, en als u ze doet, wordt er een uitzondering gemaakt, maar niet de bedoelde!
Geldig in Python 2, maar niet in Python 3is het volgende :
raise ValueError, 'message' # Don't do this, it's deprecated!
Alleen geldig in veel oudere versies van Python(2.4 en lager), zie je misschien nog steeds mensen snaren verhogen:
raise 'message' # really really wrong. don't do this.
In alle moderne versies zal dit in feite een TypeError
opleveren, omdat je geen BaseException
-type verhoogt. Als je niet op zoek bent naar de juiste uitzondering en geen recensent hebt die op de hoogte is van het probleem, kan het in productie worden genomen.
Voorbeeld van gebruik
Ik roep Exceptions op om consumenten te waarschuwen voor mijn API als ze deze verkeerd gebruiken:
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)))
Maak indien nodig uw eigen fouttypes
“Ik wil met opzet een fout maken, zodat het in de uitzondering zou komen”
U kunt uw eigen fouttypes maken. Als u wilt aangeven dat er iets specifieks mis is met uw toepassing, hoeft u alleen maar het juiste punt in de uitzonderingshiërarchie te subclasseren:
class MyAppLookupError(LookupError):
'''raise this when there's a lookup error for my app'''
en gebruik:
if important_key not in resource_dict and not ok_to_be_missing:
raise MyAppLookupError('resource is missing, and that is not ok.')
Antwoord 2, autoriteit 15%
DOE DIT NIET. Het verhogen van een kale
Exception
is absoluut niethet juiste om te doen; zie in plaats daarvan Het uitstekende antwoord van Aaron Hall.
Kan niet veel pythonischer worden dan dit:
raise Exception("I know python!")
Bekijk de documenten over de raise-statementvoor python als je wil graag meer informatie.
Antwoord 3, autoriteit 2%
In Python3 zijn er 4 verschillende syntaxen voor rasing-uitzonderingen:
1. raise exception
2. raise exception (args)
3. raise
4. raise exception (args) from original_exception
1. uitzondering verhogen vs. 2. uitzondering verhogen (args)
Als u raise exception (args)
gebruikt om een exception op te heffen, dan worden de args
afgedrukt wanneer u het exception-object afdrukt – zoals in het onderstaande voorbeeld.
#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
-statement zonder argumenten verhoogt de laatste uitzondering.
Dit is handig als u enkele acties moet uitvoeren nadat u de uitzondering hebt opgevangen en deze vervolgens opnieuw wilt verhogen. Maar als er eerder geen uitzondering was, verhoogt het raise
-statement de TypeError
Exception.
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. uitzondering (args) verhogen van original_exception
Deze instructie wordt gebruikt om exception chaining te creëren waarin een exception die wordt gegenereerd als reactie op een andere exception, de details van de originele exception kan bevatten – zoals weergegeven in het onderstaande voorbeeld.
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__)
Uitvoer:
ZeroDivisionError -- division by zero
MyException Zero Division
division by zero
Antwoord 4
Voor het veelvoorkomende geval waarin je een uitzondering moet maken als reactie op een aantal onverwachte omstandigheden, en die je nooit van plan bent te vangen, maar gewoon snel wilt falen zodat je vanaf daar kunt debuggen als het ooit gebeurt – de meest logische. lijkt AssertionError
te zijn:
if 0 < distance <= RADIUS:
#Do something.
elif RADIUS < distance:
#Do something.
else:
raise AssertionError("Unexpected value of 'distance'!", distance)
Antwoord 5
Lees eerst de bestaande antwoorden, dit is slechts een aanvulling.
Merk op dat je uitzonderingen kunt maken met of zonder argumenten.
Voorbeeld:
raise SystemExit
verlaat het programma, maar je wilt misschien weten wat er is gebeurd. Dus je kunt dit gebruiken.
raise SystemExit("program exited")
hiermee wordt “programma afgesloten” afgedrukt naar stderr voordat het programma wordt afgesloten.
Antwoord 6
Alleen om op te merken: er zijn momenten waarop u WEL generieke uitzonderingen wilt afhandelen. Als je een heleboel bestanden verwerkt en je fouten vastlegt, wil je misschien elke fout die optreedt voor een bestand opvangen, het loggen en doorgaan met het verwerken van de rest van de bestanden. In dat geval een
try:
foo()
except Exception as e:
print(e) # Print out handled error
Blok is een goede manier om het te doen. U wilt nog steeds raise
Specifieke uitzonderingen, zodat u weet wat ze bedoelen, hoewel.
7
Een andere manier om een uitzonderingen te gooien is assert
. U kunt gebruik maken van Assert om te verifiëren van een voorwaarde wordt voldaan, indien niet, dan zal het AssertionError
verhogen. Voor meer informatie hebt u een kijkje hier .
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))
8
U moet daarvoor de verhoging van Python leren.
Het moet in het try-blok worden bewaard.
Voorbeeld –
try:
raise TypeError #remove TypeError by any other error if you want
except TypeError:
print('TypeError raised')