Is finally in Python added just for better readability - python

On this link (https://docs.python.org/2/tutorial/errors.html#defining-clean-up-actions) following is said:
A finally clause is always executed before leaving the try statement, whether an exception has occurred or not.
CODE 1:
try:
print "Performing an action which may throw an exception."
except Exception, error:
print "An exception was thrown!"
print str(error)
else:
print "Everything looks great!"
finally:
print "Finally is called directly after executing the try statement whether an exception is thrown or not."
OUTPUT 1:
Performing an action which may throw an exception.
Everything looks great!
Finally is called directly after executing the try statement whether an exception is thrown or not.
CODE 2:
try:
print "Performing an action which may throw an exception."
raise Exception('spam', 'eggs') # This is new
except Exception, error:
print "An exception was thrown!"
print str(error)
else:
print "Everything looks great!"
finally:
print "Finally is called directly after executing the try statement whether an exception is thrown or not."
OUTPUT 2:
Performing an action which may throw an exception.
An exception was thrown!
('spam', 'eggs')
Finally is called directly after executing the try statement whether an exception is thrown or not.
What I get from this is that else is executed only when there is no exception.
QUESTION:
Is finally used just for better readability ?
Because I can just put this print statement after try, like in this code.
CODE 3:
try:
print "Performing an action which may throw an exception."
#raise Exception('spam', 'eggs') # with this line or without last print is done
except Exception, error:
print "An exception was thrown!"
print str(error)
else:
print "Everything looks great!"
print "Finally is called directly after executing the try statement whether an exception is thrown or not."

There are circumstances where the finally suite is always executed, but your print statement would not:
When there is an unhandled exception in your try.
When your try is in a loop (while or for) and you used a break or continue statement
When your try is in function and you used a return statement.
The finally suite then is used to guarantee that code is executed, regardless of what happens in the try block, even when exited before reaching the end of the block.
Compare:
def foo():
try:
print "Performing an action which may throw an exception."
return
except Exception as error:
print "An exception occured!", error
finally:
print "Cleaning up"
with
def bar():
try:
print "Performing an action which may throw an exception."
return
except Exception as error:
print "An exception occured!", error
print "Cleaning up"
In bar() the last message is not printed:
>>> foo()
Performing an action which may throw an exception.
Cleaning up
>>> bar()
Performing an action which may throw an exception.

The finally code block is always executed, whether or not an exception is thrown. This is true in most (I wanted to say all but ...) other languages: C#, Java, etc.
Its function is to allow the execution of clean-up code -- close opened resources, de-allocate memory, etc. -- for the program to continue/terminate its execution in a clean and safe way.

Related

Does a try except stop right away in python if an exception is found?

If I have a try except block in my python code, and the first line of my try statement raises an exception will it automatically move on to exception or will it finish the try block first?
try:
int(string)
string = "This was a mistake, can't int string"
except:
pass
Here is it checking if it can int(string), which it can't, and then it immediately moves onto except, or does it do the string assignment first?
When I run it, it seems like it stops right away, but I want to know if that's happening for sure or something else.
Thanks
Let's try it.
try:
1/0
print("what?")
except:
print("nope")
Output:
nope
>>>
When an exception is raised it moves on to the except.
From the python docs, I found this,
"The try statement works as follows.
First, the try clause (the statement(s) between the try and except keywords) is executed.
If no exception occurs, the except clause is skipped and execution of the try statement is finished.
If an exception occurs during execution of the try clause, the rest of the clause is skipped. Then if its type matches the exception named after the except keyword, the except clause is executed, and then execution continues after the try statement.
If an exception occurs which does not match the exception named in the except clause, it is passed on to outer try statements; if no handler is found, it is an unhandled exception and execution stops with a message as shown above."
Cheers!
Hope it helps!
#the try block is to run the process
try:
string = "This was a mistake, can't int string"
#you are parsing the string into an int
int(string)
#this block is to capture the exception when it is raised
except:
#here I am just printing the exception
print('Exception')
#the pass is to pass the execution and follow the remaining process.
pass
Output:
Exception
>>>
Well, that the whole point of an error handler. When an error occurs in out program, it crashes, it won't simply skip the error line.
try:
int(string)
string = "This was a mistake, can't int string"
except:
pass
So if the try block finishes even after an error occurred in the middle, then the error handler'd seem a bit pointless.
There seem to be some issue with your program and maybe your understanding of the try except block.
First of all, from the block of code you have provided, it seems to me like string isn't even defined yet when you try to pass int(string).
Secondly, the string variable which you seem to be defining under seems to me like is something you are trying to print to the console once the program spits out an error and passes to the except block. If this is what you are trying to do, then your code should look something like this:
try:
int(string)
except:
print("This was a mistake, can't int string")
If you were to run the code provided above, you would indeed confirm that the try except statement is working as it would print "This was a mistake, can't int string" into the console instead of giving an error. Hope this was somewhat helpful and understandable. You got this chief, keep grinding!

Handling multiple exceptions in python?

I want to pause a python script when Crtl+C is pressed but to handle the rest of exceptions with different code.
If I got:
except KeyboardInterrupt:
print '\nPausing... (Hit ENTER to continue, type quit to exit.)'
try:
response = raw_input()
if response == 'quit':
break
print 'Resuming...'
except KeyboardInterrupt:
print 'Resuming...'
continue
except Exception, e:
print traceback.print_exc()
continue
sleep(170)
Won't second except go also for KeyboardInterrupt, isn't a keyboard interrupt supposed to be an exception?
Won't second except go also for KeyboardInterrupt, isn't a keyboard interrupt supposed to be an exception?
Well, this is interesting... Apparently it is not a subclass of the Exception class, but is child to a superclass called BaseException.
Python's doc Built-in Exceptions explains why they implemented it this way:
The exception inherits from BaseException so as to not be accidentally caught by code that catches Exception and thus prevent the interpreter from exiting.
And it can be checked like this:
>>> issubclass(KeyboardInterrupt, Exception)
False
>>> issubclass(KeyboardInterrupt, BaseException)
True
>>> issubclass(Exception, BaseException)
True
Nevertheless, even if you changed your last except block to catch a BaseException instead of a Exception, it would still not enter it (because your inner except KeyboardInterrupt avoids the exception to be thrown to the outer indentation or "parent" levels).
In case you also removed this inner except KeyboardInterrupt block, the exception would be thrown to the outer indentation, which I assume it does not exist (given your indentation level) and the execution would terminate...

What happens exactly internally when I terminate my Python script using Ctrl+c?

These days I am learning Python's Exception handling features deeply. I encountered exception SystemExit. While reading about this from official Python Docs I got question in mind that what exactly would have happen when I terminate Python script by pressing Ctrl+c?
lets take this sample code:
def func1(a,b):
print "func1: "+str(a/b)
#some more functions
def func2(a,b):
print "func2: "+str(a/b)
#some more functions
if __name__=="__main__":
import random
count=0
for i in range(1000000):
count=count+1
print "count: "+str(count)
try:
func1(random.randint(-2,3),random.randint(-2,3))
except KeyboardInterrupt:
raise
except:
print "error in func1"
try:
func2(random.randint(-2,3),random.randint(-2,3))
except KeyboardInterrupt:
raise
except:
print "error in func2"
print "\n"
In this sample code I am catching KeyboardInterrupt so I can stop my script by pressing Ctrl+c. Should I catch SystemExit too to make this code more mature? if yes then why? actually this question is source of my main question which appear on title. so don't consider that I am asking two different question in one post.
You usually not need to catch SystemExit as it is what makes exit() and sys.exit() functions work:
sys.exit([arg])
Exit from Python. This is implemented by raising the SystemExit exception, so cleanup actions specified by finally clauses of try statements are honored, and it is possible to intercept the exit attempt at an outer level.
Example:
try:
exit()
except SystemExit:
print "caught"
Therefore, you usually don't want to catch all exceptions in the first place (by using an empty except: clause). The best approach is generally to make your exception handlers as specific as possible. It otherwise makes debugging your application exceptionally hard, as it either hides errors entirely or at least makes it hard to diagnose the details.
The only exception your functions can raise is a ZeroDivisionError, so you should only catch that one:
import random
if __name__ == "__main__":
for count in range(1000000):
print "count:", count
try:
func1(random.randint(-2, 3),random.randint(-2, 3))
except ZeroDivisionError:
print "error in func1"
try:
func2(random.randint(-2, 3),random.randint(-2, 3))
except ZeroDivisionError:
print "error in func2"
print "\n"
Your title says something different than the body of your question.
To the title:
What happens internally is that python captures the SIGINT and raises a KeyboardInterrupt exception from it.
To the text:
You don't want to do except:.
Instead, you want
if __name__=="__main__":
try:
import random
count=0
for i in range(1000000):
count=count+1
print "count: "+str(count)
try:
func1(random.randint(-2,3),random.randint(-2,3))
except Exception, e:
print "error in func1", e # or something...
try:
func2(random.randint(-2,3),random.randint(-2,3))
except Exception, e:
print "error in func2", e # or something...
print "\n"
except Exception:
raise # any other "normal" exception.
except: # Here it is ok, as you handle most exceptions above.
pass
Most "normal" exception which should normally be handled derive from Exception. Those which have an internal meaning and should normally not be caught (except on global level) don't derive from Exception.
These are KeyboardInterrupt, SystemExit and GeneratorExit.
If you're uncertain what exceptions the code you're calling throws to indicate errors then you should (in order of preference):
Find out what it is documented to throw and only catch that
catch Exception, not everything.
Neither KeyboardInterrupt nor SystemExit is a subclass of Exception, but all of the standard Python exceptions used to indicate errors are.

Python try except

try:
#statement 1
#statement 2
except Exception, err:
print err
pass
This may be very trivial but I never actually thought about it until now and I found myself not being able to answer the following questions:
Does statement 2 gets executed if an error is raised in statement 1?
How does Exception deal with in a case where an error is raised for both statement 1 and statement 2? Which error does it print out in the above code? Both?
The answer is "no" to both of your questions.
As soon as an error is thrown in a try/except block, the try part is immediately exited:
>>> try:
... 1/0
... print 'hi'
... except ZeroDivisionError, e:
... print 'error'
...
error
>>>
As you can see, the code never gets to the print 'hi' part, even though I made an except for it.
You can read more here.
From Python docs:
If an exception occurs during execution of the try clause, the rest of
the clause is skipped. Then if its type matches the exception named
after the except keyword, the except clause is executed, and then
execution continues after the try statement.
So as soon as an error occurs, it skips to the exception
http://docs.python.org/2/tutorial/errors.html
Upon an exception being raised control leaves the try block at the point the exception is raised and is given to the appropriate except block. If statement 1 throws an exception, statement 2 will not execute.
This answers your second question as well: it's not possible for the scenario you describe to happen.
1) Does statement 2 gets executed if an error is raised in statement 1?
No. Exception will be raised and catched.
As I understand python will move up the stack and looks for an exception handler in the caller
2) How does Exception deal with in a case where an error is raised for both statement 1 and statement 2? Which error does it print out in the above code? both?
statement 2 will not be run so no exceptions will be raised for it
any exception from the try block will be caught. That is why for all try/except clauses, limit the try clause to the absolute minimum amount of code necessary. Again, this avoids masking bugs.
1) Does statement 2 gets executed if an error is raised in statement
1?
nope, statement 2 is not executed
2) How does Exception deal with in a case where an error is raised for
both statement 1 and statement 2? Which error does it print out in the
above code? both?
only statement 1 has a chance to raise an error, see above,
NOTE: if you want statement 2 to execute always, you can use finally with the try/except

Catch exception throw from inside of the with statement

zip_file_name = "not_exist.py"
try:
with zipfile.ZipFile(zip_file_name) as f_handle:
print("open it successfully")
except (zipfile.BadZipfile, zipfile.LargeZipFile), e:
print(e)
Is this the correct way to handle exception throw by a with statement?
Yes, this is how you would want to handle exceptions from inside a with statement. ContextManagers (that implement the behavior behind the with statement) can handle exceptions but should only do so to properly clean up resources used by the object.
Here's a snippet from the relevant documentation:
If BLOCK raises an exception, the context manager’s exit() method
is called with three arguments, the exception details (type, value,
traceback, the same values returned by sys.exc_info(), which can also
be None if no exception occurred). The method’s return value controls
whether an exception is re-raised: any false value re-raises the
exception, and True will result in suppressing it. You’ll only rarely
want to suppress the exception, because if you do the author of the
code containing the ‘with‘ statement will never realize anything went
wrong.
Yes, that's fine.
Another alternative is:
try:
f_handle = zipfile.ZipFile(zip_file_name)
# no more code here
except (zipfile.BadZipfile, zipfile.LargeZipFile), e:
print(e)
else:
with f_handle:
print("open it successfully")
This prevents you from accidentally catching an exception from the body of the with statement in your except handler.

Categories

Resources