Python 2.6.5 (r265:79063, Oct 1 2012, 22:07:21)
I have this:
def f():
try:
print "a"
return
except:
print "b"
else:
print "c"
finally:
print "d"
f()
This gives:
a
d
and not the expected
a
c
d
If I comment out the return, then I will get
a
c
d
How do I remember this behavior in python?
When in doubt, consult the docs:
The optional else clause is executed if and when control flows off the end of the try clause
Currently, control “flows off the end” except in the case of an exception or the execution of a return, continue, or break statement.
Since you're returning from the body of the try block, the else will not be executed.
finally blocks always happen, save for catastrophic failure of the VM. This is part of the contract of finally.
You can remember this by remembering that this is what finally does. Don't be confused by other control structures like if/elif/else/while/for/ternary/whatever statements, because they do not have this contract. finally does.
The else block hooked up to a try block is not special in terms of exception mechanics - it's similar to just putting code in the body of the function after the try block. The only function is being able execute "normal" code between a try block and a finally block. This does mean however that if the function returns before getting to the else block it will never execute.
Take a look at Python documentation!
You would use this for exception handling, bookmark this page!
http://docs.python.org/2/tutorial/errors.html
You enter the try block.
You print "a".
You encounter the return statement and the function returns.
Since finally blocks always execute, though, everything in the finally block happens before the function actually ends its execution.
The else block is only entered if the try block has been completed and no exception occurred. Because you returned in the try block, it wasn't completed, even though no exception occurred nonetheless. It is as if you never had a try/else block at all, and you put all the code on the same level of indentation.
try/else exists more for the sake of code organization; unless a finally block is added, it is the same thing as using no else block at all. The following are functionally equivalent:
try:
print "foo"
except:
print "woops"
else:
print "bar"
try:
print "foo"
except:
print "woops"
print "bar"
However, you must use else if you are going to use finally. This has no meaning:
try:
print "foo"
except:
print "woops"
print "bar"
finally:
print "done"
What was the finally supposed to refer to in this case? Ergo you must use else if you are going to use finally unless you did not intend for anything to happen after the try block but before the finally.
When a return, break or continue statement is executed in the try suite of a try…finally statement, the finally clause is also executed ‘on the way out.’ A continue statement is illegal in the finally clause. (The reason is a problem with the current implementation — this restriction may be lifted in the future).
This is actually from the documentation.
Related
I have this code:
try:
condition1==True
condition2==True
condition2==True
print("ok")
except:
print("no")
I am absolutely certain that condition2 is not True but is False. but still i get printed "ok", same thing happens even if i replace condition2==True with condition2==False
I've tried several times, I've done more tests using other methods. I even thought it might be a bug in the Python version I use because it's absurd.How is it possible? what could this be due to?
EDIT: if I use an IF statement , it works!!!
Python's try-except blocks do not work with conditions like that. Instead, a try block will try to execute a piece of code unless it runs into some exception along the way. If it does so, the except block will be activated and code inside it will be executed.
Essentially: conditions don't matter for try-except blocks.
This is a sample:
a = 100
b = 0
try:
my_var = a/b
except Exception as e:
print(e)
try running it, see what error you get!
I found an interesting piece of code in python:
def x(cond):
if cond:
pass
print('Still running!')
x(True)
I would expect this not to print anything, but it prints Still running!. What is happening here?
As per Python docs:
pass is a null operation — when it is executed, nothing happens.
Source - https://docs.python.org/3.5/reference/simple_stmts.html#pass
As such, pass does not do anything and all statements after pass will still be executed.
Another way of thinking about this is that pass is equivalent to any dummy statement:
def x(cond):
if cond:
"dummy statement"
print('Still running!')
pass does not mean "leave the function", it just means ... nothing. Think of it as a placeholder to say that you do not do anything there (for example if you do not have implemented something yet).
https://docs.python.org/3.5/tutorial/controlflow.html#pass-statements
If you want to exit the function, you just return or return None
By the way other useful statements are break to exit the latest loop and continue to exit the current iteration of the loop and directly go to the next one.
Pass does nothing. When the program gets there, it says "ok skip this!".
Pass can be used to define functions ahead of time. For example,
def function_somebody_is_going_to_write_later():
pass
def function_I_am_going_to_write_later():
pass
That way you could write a file with functions that other people might work on later and you can still execute the file for now.
It is conventional to use pass statement in python like the following piece of code.
try:
os.makedirs(dir)
except OSError:
pass
So, 'pass' bascially does not do anything here. In this case, why would we still put a few codes like this in the program? I am confused. Many thanks for your time and attention.
It's for the parser. If you wrote this:
try:
# Code
except Error:
And then put nothing in the except spot, the parser would signal an error because it would incorrectly identify the next indentation level. Imagine this code:
def f(x):
try:
# Something
except Error:
def g(x):
# More code
The parser was expecting a statement with a greater indentation than the except statement but got a new top-level definition. pass is simply filler to satisfy the parser.
This is in case you want the code to continue right after the lines in the try block. If you won't catch it - it either skips execution until it is caught elsewhere - or fails the program altogether.
Suppose you're creating a program that attempts to print to a printer, but also prints to the standard output - you may not want it to file if the printer is not available:
try:
print_to_printer('hello world')
except NoPrinterError:
pass # no printer - that's fine
print("hello world")
If you would not use a try-catch an error would stop execution until the exception is caught (or would fail the program) and nothing would be printed to standard output.
The pass is used to tell the program what to do when it catches an error. In this particular case you're pretty much ignoring it. So you're running your script and if you experience an error keep going without worrying as to why and how.
That particular case is when you are definite on what is expected. There are other cases where you can break and end the program, or even assign the error to a variable so you can debug your program by using except Error as e.
try:
os.makedirs(dir)
except OSError:
break
or:
try:
os.makedirs(dir)
except OSError as e:
print(str(e))
try:
# Do something
except:
# again some code
# few more code
There are two uses of pass. First, and most important use :- if exception arises for the code under try, the execution will jump to except block. And if you have nothing inside the except block, it will throw IndentationError at the first place. So, to avoid this error, even if you have nothing to do when exception arises, you need to put pass inside except block.
The second use, if you have some more code pieces after the try-except block (e.g. again some code and few more code), and you don't put pass inside except, then that code piece will not be executed (actually the whole code will not be executed since compiler will throw IndentationError). So, in order to gracefully handle the scenario and tell the interpreter to execute the lines after except block, we need to put pass inside the except block, even though we don't want to do anything in case of exception.
So, here pass as indicated from name, handles the except block and then transfers the execution to the next lines below the except block.
This is some code that is behaving peculiarly. This is a simplified version of the behavior that I've written. This will still demonstrate the weird behavior and I had some specific questions on why this is occurring.
I'm using Python 2.6.6 on Windows 7.
def demo1():
try:
raise RuntimeError,"To Force Issue"
except:
return 1
else:
return 2
finally:
return 3
def demo2():
try:
try:
raise RuntimeError,"To Force Issue"
except:
return 1
else:
return 2
finally:
return 3
except:
print 4
else:
print 5
finally:
print 6
Results:
>>> print demo1()
3
>>> print demo2()
6
3
Why is demo one returning 3 instead of 1?
Why is demo two printing 6 instead of printing 6 w/ 4 or 5?
Because finally statements are guaranteed to be executed (well, presuming no power outage or anything outside of Python's control). This means that before the function can return, it must run the finally block, which returns a different value.
The Python docs state:
When a return, break or continue statement is executed in the try suite of a try…finally statement, the finally clause is also executed ‘on the way out.’
The return value of a function is determined by the last return statement executed. Since the finally clause always executes, a return statement executed in the finally clause will always be the last one executed:
This means that when you try to return, the finally block is called, returning it's value, rather than the one that you would have had.
The execution order is:
try block all completes normally -> finally block -> function ends
try block run and get into exception A -> finally block -> function ends
try block make a return value and call return -> finally block -> popup return value -> function ends
So, any return in the finally block will end the steps in advance.
Note that there has been PEP601 to forbid return statements from finally clauses, but it has been rejected.
It has however been added to the style guide in PEP8 that it should be avoided.
I have two questions on exception handling.
Q1) I am slightly unsure as to when exactly the operations within else will be carried out in exception handling. I am unsure when the else block would be executed, which doesn't occur in the code below:
def attempt_float(SecPrice,diffprice):
try:
return float(SecPrice)
except:
return diffprice
else:
print "Did we succeed?"
print attempt_float('7','3')
Q2) When I run the code below:
def attempt_float(SecPrice,diffprice):
try:
return float(SecPrice)
except:
return diffprice
else:
print "Did we succeed?"
finally:
print "Yasdsdsa"
print attempt_float('7','3')
I am unclear as to why the output is:
Yasdsdsa
7.0
When Python encounters a return-statement inside a function, it immediately returns (exits) from the function. This means that when you do:
try:
return float(SecPrice)
...
else:
print "Did we succeed?"
"Did we succeed?" will never be printed because you returned in the try: block, thereby skipping the execution of the else: block.
Your second code piece is different however because you used a finally: block. Code inside a finally: block is always executed, no matter if an exception is raised, you return from a function, etc. This is to ensure that any cleanup code which is important (i.e. frees resources) is always executed and not accidentally skipped.
You can read about this behavior in the docs both here:
When return passes control out of a try statement with a finally
clause, that finally clause is executed before really leaving the
function.
as well as here:
When a return, break or continue statement is executed in the try
suite of a try...finally statement, the finally clause is also
executed "on the way out."
As for why the output is:
Yasdsdsa
7.0
and not:
7.0
Yasdsdsa
the answer is that the print "Yasdsdsa" line is executed in the finally: block before Python is able to print 7.0 (the return value of attempt_float). Put simply, the execution path for Python is:
Return float(SecPrice).
Run the finally: block.
Resume normal execution with the print attempt_float('7','3') line and print 7.0.
In the first case, you return within try, so you never hit the else statement.
In the second one, the finally is executed regardless of how try is exited. From the python docs:
A finally clause is always executed before leaving the try statement, whether an exception has occurred or not. (...) The finally clause is also executed “on the way out” when any other clause of the try statement is left via a break, continue or return statement.
Here is a good example of the order of execution:
>>> def divide(x, y):
... try:
... result = x / y
... except ZeroDivisionError:
... print "division by zero!"
... else:
... print "result is", result
... finally:
... print "executing finally clause"
...
>>> divide(2, 1)
result is 2
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause
Be sure to read the docs on exceptions!