Handmatig verhogen (gooien) een uitzondering in Python

Hoe kan ik een uitzondering in Python verhogen, zodat het later kan worden gepakt via een exceptBLOCK?


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

Gebruik in plaats daarvan de meest specifieke uitzonderingsconstructeur die semantisch past bij uw probleem .

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 argsATRIBUTE op de ExceptionObject. 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 messageAttribuut is toegevoegd aan BaseExceptionTen gunste van het aanmoedigen van gebruikers om uitzonderingen te ondersteunen en te stoppen met het gebruik van args, maar De introductie van messageen de oorspronkelijke afschrijving van Args is ingetrokken .

Beste praktijken: exceptclausule

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 raiseom 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 argsinstellen 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_infogebruikt, 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 TypeErroropleveren, 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 Exceptionis 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 argsafgedrukt 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 TypeErrorException.

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 AssertionErrorte 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 raiseSpecifieke 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 AssertionErrorverhogen. 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')

Other episodes