From a list of exception treatment (but without covering each possible exception) how can I end (break) before reaching the generic treatment?
See below the point where I would like to "break" and just return from function or continue over the generic treatment:
try:
# do_f
except (ex1,ex2,ex3) as e:
# treat exception
except special_exception as e:
# treat this one
# do not continue to generic treatment/break <---
except Exception as e:
# generic treatment
In a try statement, only the first matching except clause will be executed.
All other except clauses will not be executed and you don't need to "break".
Reference: https://docs.python.org/3/reference/compound_stmts.html#the-try-statement
Related
In this piece of code, I could write a simple except clause without writing Exception in front of it. I mean the last line could be like this :
except:
print('Hit an exception other than KeyError or NameError!')
What is the point of writing Exception in front of an except clause ?
try:
discounted_price(instrument, discount)
except KeyError:
print("There is a keyerror in your code")
except NameError:
print('There is a TypeError in your code')
except Exception:
print('an exception occured')
I tried writing an except clause without Exception keyword and it worked the same.
Thank you guys for your answers . I know the point of catching specific errors. If I want to ask more clearly , what is the difference between two clauses :
except Exception:
print('an exception occured')
except :
print('an exception occured')
The point of specifying the Exception is that ONLY that Exception will be caught, if you do not specify any Exception, then ALL Errors and Exceptions will be caught potentially masking bugs.
For example let's say that I want to read a file if it exists or otherwise print a message to the user, I can write:
try:
with ope("example.txt", "r") as f:
print(f.read())
except:
print("File not found")
But while this code runs fine without raising any exceptions, this code will never read the file, even if it exists!!!
This is because I wrote ope instead of open and the NameError was caught by my bare except, If I write the except in the correct way:
try:
with ope("example.txt", "r") as f:
print(f.read())
except FileNotFoundError:
print("File not found")
Now I can properly debug my code:
Traceback (most recent call last):
File "/home/riccardo/types.py", line 4, in <module>
with ope("example.txt", "r") as f:
NameError: name 'ope' is not defined
A bare expect
try:
...
except:
pass
or catching any exception whatsoever
try:
...
except Exception:
pass
are bad practice, because you can be hiding bug or be interfering with the normal procedure of the program.
You should only catch exception that you know how to handle, everything else you should let it propagate.
For some example:
Hide bug: it can hide some typo in your code as Caridorc example show making you think that you had a problem different than the real problem
Interfering with the normal procedure: you can make it an unexpectedly unkillable program or get in the way of the normal procedure of the program by discarding an exception that another part of the code was expecting.
like for example
while True:
try:
print("running")
except:
print("I'm immortal muahahaha")
this piece of code now you can't stop with you usual control-z (control-z throw and KeyboardInterrupt exception into your program) so you now need to close the whole interpreter/kill it with the task admin just to stop it, and if this was unintended you just introduced a new bug and depending on what you're doing it can be catastrophic.
To illustrate how catastrophic it can be, consider the following hypothetical case: imagine you make so benign function for a medical device and you put something like this
try:
...
except:
print("some error happens")
now it just so happens that while you piece of code was running a HeartAttack exception was raised and your catch it all and ignore piece of code will do, well, just that, and here is the twist this device was a pacemaker... well, congratulation you just killed the poor guy.
And that is why you should only catch the exception you know how to deal with, everything else you let it pass and hope that somebody along the line know how to deal with it, like in the example above, you and your piece of code don't know how to deal with a HeartAttack, but the pacemaker do and the pacemaker was the one that call your piece of code let it deal with it...
for a no so extreme example consider this simple code
def get_number_from_user():
while True:
try:
return int(input("write a number: "))
except:
print("not a valid number try again")
if your user was done with your program and this happens to be the thing running he/she might want to kill it with a control-z as you usually do with any program, but it will find that it doesn't work, the correct way here is to catch the error we know how to deal with in this case, namely ValueError, everything else isn't this function business
def get_number_from_user():
while True:
try:
return int(input("write a number: "))
except ValueError:
print("not a valid number try again")
You also ask about the difference between
try:
...
except:
pass
and this
try:
...
except Exception:
pass
the difference is that a bare except can catch any and all kind of exception, that in python is anything that is or inherit from BaseException that sit at the top of the exception hierarchy, while except Exception will catch only Exception itself or anything that inherit from it (the same apply for any particular exception you put there), this small distinction allow to make some exceptions more special than other, like the aforementioned KeyboardInterrupt that inherit from BaseException instead of Exception, and that is used to signal that the user wants to terminate this program, so you should do so and this distinction is made basically so new programmers don't shoot themselves in the foot when using except Exception
Just to add to the answer provided by #Caridorc, by specifying each error separately, you can run specific error handling code pertaining to that error when the exception arises. If for example the file does not exist, you can print message to that effect. If however, it fails to print because you mistyped g instead of f, you can print a message to say that the variable is not recognised ( separate code for separate error captures). For exmple:
g = 100 # Unrelated variable declared previously
try:
with open("example.txt", "r") as f:
x=print(f.read())
except FileNotFoundError:
print("File not found")
except AttributeError:
print("Reading wrong variable")
except Exception as e:
print("Unknown Error", e)
Note also the last exception except Exception as e:. This is the same as just except: but allows you to handle all other errors that do not fit onto previous captures and retrieve e - the error message that is generated by compiler. There is effectively no difference between except: and except Exception: in terms of execution
Consider the code:
a = 5
b = 0
x = a / b
Executing this will alert you to the fact that you have attempted to divide a float by zero but it will crash your code.
Now consider:
a = 5
b = 0
try:
x = a / b
except: # or 'except Exception:'
print("An exception was raised")
This will raise an exception that is handled by printing a message that an error occurred. You code will not crash but you do not know how to properly handle the code because you do not know what the exception was, just that one occurred.
Now consider:
a = 5
b = 0
try:
x = a / b
except Exception as e:
print("An exception was raised, generating error", e)
Now your code does not crash. Is handled and you know what the error was.
The purpose of writing "Exception" in front of an except clause is to catch all possible exceptions that can occur in the code. By specifying "Exception", you are telling the interpreter to handle any type of exception that might be raised. The more specific the exception specified in the except clause, the more targeted the handling of the exception can be. For example, if you only want to handle "KeyError" exceptions, you can specify that explicitly in the except clause, as in the first example.
I'm trying to understand how Python handles exceptions within exception handling. For example, consider the following:
try:
try:
1/0
finally:
raise Exception("Exception!")
except Exception as e:
print(e)
My understanding is that both exceptions thrown by this code (both the ZeroDivisionError and the generic exception thrown in the finally block) should be "handled" by the outside except block...but how does Python decide which one to assign to e? Running the code on my machine, it seems that Python chooses to assign the "most recent" exception (the one thrown in the finally block) to e.
Is this generally true? Also, in a case like this where multiple exceptions might be thrown inside of error handling that are all handled by an outer except block, is there a way for the outer except block to step through each of the errors separately?
The Python docs have this:
If an exception occurs during execution of the try clause, the
exception may be handled by an except clause. If the exception is not
handled by an except clause, the exception is re-raised after the
finally clause has been executed.
So in your example, you don't catch the inner exception, this causes the finally block to execute (before re-raising the original exception). The exception in finally kicks it to the outside block before there is a chance to re-raise the original exception. The outside block never sees the divide-by-zero exception.
This is similar to returning from a function in finally:
def ex_test():
try:
try:
1/0
finally:
return "finally"
except Exception as e:
print(e) # never gets here
ex_test()
# only prints "finally"
# never re-raises the exception
You can get some information about the original exception. From the docs:
When raising (or re-raising) an exception in an except or finally
clause context is automatically set to the last exception caught;
if the new exception is not handled the traceback that is eventually
displayed will include the originating exception(s) and the final
exception.
So:
try:
try:
1/0
finally:
raise Exception("Exception!")
except Exception as e:
print(e.__context__)
# prints: "division by zero"
Is there a way to temporary stop catching some exception?
The point is that when you have more exceptions which are being catched in a code and you want to comment them because you want to see all the things printed when exception is raised (print exception is not sufficient), you have to comment try, except, code in except, finally, code in finally and change an indent of the code where the exception can be raised. This commenting is very time-consuming when you have to do it many times.
#try:
pel.check_one_destination()
#except Exception as e:
#pel.driver.save_screenshot('log.png')
#print e
You can just add raise keyword inside the except block and it will raise the caught exception back. Found it useful during testing.
Example -
try:
#code that leads to exception
except Exception as e:
#handle exception
raise #for testing what the exception was, and etc.
I'm trying to make it so if the user enters in any letters it won't give any errors. It will just restart the program.
x = int(input())
try:
if x == (a, b, c): # Entering letters in the x integer will restart the program.
displayStart()
return
print('')
I have this, The print statement at the bottom becomes an invalid syntax after i've entered this "try:" Statement. Any suggestions on how to fix it?
try suites need to have an except and/or finally clause. You have neither. e.g.
try:
do_something()
except SomeExceptionName:
do_something_because_some_exception_name_was_raised_in_do_something()
Or:
try:
do_something()
finally:
do_something_even_if_exception_was_raised()
You also might want to have a look at the python tutorial.
If you think about it, what should your try suite do here? If an exception is raised, what would happen differently than normal if you have no way of handling it (via except) or cleanup action to perform (via finally)?
From the python grammer specification:
try_stmt: ('try' ':' suite
((except_clause ':' suite)+
['else' ':' suite]
['finally' ':' suite] |
'finally' ':' suite))
This is an example of a try statement:
try:
print("this will actually print, because its trying to execute the statements in the tryblock")
assert(1==0) #a blatently false statement that will throw exception
print("This will never print, because once it gets to the assert statement, it will throw an exception")
except:
print("after exception this is printed , because the assert line threw an exception")
IF the assert sttement had been assert(1==1) it would have never thrown an exception, then it would have printed the "This will never print" line, and NOT the "after exception" line
Of course there are more things involved like finally and else, but this try: except: example should be enough to get you started
You need to add an except portion to your try statement. Like this:
x = int(input())
try:
if x == (a, b, c):
displayStart()
return
except Exception as e:
print('An exception occurred: ', e)
print('')
A try needs to have its corresponding except.
As a note, it is not very good practice to catch ALL exceptions like I do. Instead of Exception, usually you would specify the particular exception you expect. For example, if I am expecting a ValueError, I would make it:
try:
...
except ValueError as ve:
print('A Value Error occurred: ', ve)
Also, you usually want to put as little code in the try-except block as possible.
I would like to know if it is possible in python to raise an exception in one except block and catch it in a later except block. I believe some other languages do this by default.
Here is what it would look like"
try:
something
except SpecificError as ex:
if str(ex) = "some error I am expecting"
print "close softly"
else:
raise
except Exception as ex:
print "did not close softly"
raise
I want the raise in the else clause to trigger the final except statement.
In actuality I am not printing anything but logging it and I want to log more in the case that it is the error message that I am not expecting. However this additional logging will be included in the final except.
I believe one solution would be to make a function if it does not close softly which is called in the final except and in the else clause. But that seems unnecessary.
What about writing 2 try...except blocks like this:
try:
try:
something
except SpecificError as ex:
if str(ex) == "some error I am expecting"
print "close softly"
else:
raise ex
except Exception as ex:
print "did not close softly"
raise ex
Only a single except clause in a try block is invoked. If you want the exception to be caught higher up then you will need to use nested try blocks.
As per python tutorial there is one and only one catched exception per one try statement.
You can find pretty simple example in tutorial that will also show you how to correctly use error formatting.
Anyway why do you really need second one? Could you provide more details on this?
You can do this using the six package.
Six provides simple utilities for wrapping over differences between Python 2 and Python 3.
Specifically, see six.reraise:
Reraise an exception, possibly with a different traceback. In the simple case, reraise(*sys.exc_info()) with an active exception (in an except block) reraises the current exception with the last traceback. A different traceback can be specified with the exc_traceback parameter. Note that since the exception reraising is done within the reraise() function, Python will attach the call frame of reraise() to whatever traceback is raised.