Faster way to avoid catching an exception - python

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.

Related

Difference between bare except and specifying a specific exception

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.

Exceptions within exception handling in Python

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"

How to manage exceptions correctly in PyQt

I am wondering how to manage multiple exceptions in pyqt
I have a function 'encodeVideo()' that may trigger multiple exceptions.
def updateFilename(self):
try:
self.model.updateFilename(self.fileName)
except type_exc.PathIsEmpty as e:
self.errorDialog.errorTypeChanged(e)
self.errorDialog.show()
def updateOutput(self):
try:
self.model.updateOutput(self.encodeDialog.output)
except (type_exc.FileAlreadyExists, type_exc.PathNotExists) as e:
self.errorDialog.errorTypeChanged(e)
self.errorDialog.show()
def encodeVideo(self):
self.updateFilename()
self.updateOutput()
In my case, it is likely to trigger errors both in updateFilname() and updateOutput. When this happens, a dialog will show up and report both errors. However, I seem to manage the exceptions in a wrong way. For example, when error in self.updateFilename() occurs, that doesn't stop my code from continuing the next code self.updateOutput().
You want to handle exceptions as a high as possible in your method call stack; this usually means that exceptions are handled in the UI where the first call was made, if inside any of your methods you need to do something if an exception occurs, you should catch and re-throw the exception, here are some examples:
In your code, the first method that is called from the UI is encodeVideo, therefore, you want to catch and handle your exceptions there:
def updateFilename(self):
self.model.updateFilename(self.fileName)
def updateOutput(self):
self.model.updateOutput(self.encodeDialog.output)
def encodeVideo(self):
try:
self.updateFilename()
self.updateOutput()
except (type_exc.PathIsEmpty, type_exc.FileAlreadyExists, type_exc.PathNotExists) as e:
self.errorDialog.errorTypeChanged(e)
self.errorDialog.show()
Rethrow the exception
Let's imagine that if the call to updatedOutput fails, you want to do something specific, in this case, you can handle the exception in the inner method, but you should rethrow it again so it is handled by the calling method:
def updateOutput(self):
try:
self.model.updateOutput(self.encodeDialog.output)
except type_exc.FileAlreadyExists, e:
print("Do something")
raise type_exc.FileAlreadyExists(e)
def encodeVideo(self):
try:
self.updateFilename()
self.updateOutput()
except (type_exc.PathIsEmpty, type_exc.FileAlreadyExists, type_exc.PathNotExists) as e:
self.errorDialog.errorTypeChanged(e)
self.errorDialog.show()
This is basically a exception and error handling problem. And hence if there is error in any block then system takes it as an error handles or exception handles. Thus if first block of code gave error , then next block contain another handler exception so it is very simple that system treating it as a blocks of errors and exception.

finally and rethowing of exception in except, raise in python

try:
#error code
except Exception as e:
print 'error',e
raise miexp("malicious error")
#userdefined exception, miexp
finally:
print 'finally'
Why the output is in the following formats?
Output:
error
finally
malicious error
Actually I expected as:
error
malicious error
finally
Why so?
miexp("malicious error") isn't handled, therefore it will end the execution of the program. On the other hand, the finally block is guaranteed to be executed.
To ensure this Python executes the finally block before actually raising the exception. From the documentation:
If an exception occurs in any of the clauses and is not handled, the exception is temporarily saved. The finally clause is executed. If there is a saved exception it is re-raised at the end of the finally clause.

Which exceptions besides OSError can subprocess.Popen() raise?

In (this section)[https://docs.python.org/3/library/subprocess.html#exceptions] about exceptions with subprocess.Popen the documentation says that "The most common exception raised is OSError".
Are there other, undocumented Exceptions that might by raised that are not of type OSError and are not due to invalid arguments?
I am asking this because I have the following code:
try:
obj = subprocess.Popen(*args)
#....
except OSError as e:
pass
and I want this to be 100% exception free. The system I am working on is Debian GNU/Linux 7.7 (wheezy).
I not only ask this for a safe way to write my program but also out of curiousity for the python os.Popen implementation. So please be a bit more specific than just saying to catch Exception.
Just catch Exception, if you want to be very sure you're catching everything. That still won't catch things like SystemExit, but most of the time you don't want to catch those anyway.
this will covers most of it:
try:
obj = subprocess.Popen(*args)
#....
except OSError as e: # to catch OSError
print e
pass
except ValueError as e: # to catch ValueError
print e
pass
except:pass # others

Categories