python: try/except/else and continue statement - python

Why is the output of the below python code snippet NOT just No exception:1, since during first iteration there is no exception raised. From python docs (https://docs.python.org/2.7/tutorial/errors.html).
The try ... except statement has an optional else clause, which, when
present, must follow all except clauses. It is useful for code that
must be executed if the try clause does not raise an exception.
$ cat hello.py
for x in range(1,10):
try:
if x == 1:
continue
x/0
except Exception:
print "Kaput:%s" %(x)
else:
print "No exception:%s" %(x)
break
$ python hello.py
Kaput:2
Kaput:3
Kaput:4
Kaput:5
Kaput:6
Kaput:7
Kaput:8
Kaput:9
$ python -V
Python 2.7.8

The tutorial gives a good start, but is not the language reference. Read the reference here.
Note in particular:
The optional else clause is executed if and when control flows off the end of the try clause.
clarified by footnote 2:
Currently, control “flows off the end” except in the case of an exception or the execution of a return, continue, or break statement.
So your use of continue is explicitly addressed by that.

Your code has a continue, so it never gets to the else block. To achieve your result, you can not get to the continue:
Code:
for x in range(1, 10):
try:
if x != 1:
x / 0
except Exception:
print "Kaput:%s" % (x)
else:
print "No exception:%s" % (x)
break
Result:
No exception:1

It has to do with your use of continue and break. I think this is the functionality you're going for. Basically, continue does not skip to the else statement, it continues on with the code (passed the try statement). And, break breaks the for loop, thus producing no more output, so I removed that statement.
for x in range(1,10):
try:
if x != 1:
x/0
except Exception:
print "Kaput:%s" %(x)
else:
print "No exception:%s" %(x)

This is because of the continue statement... its taking the control to for statement.. try removing the continue and add a conditional statement for x/0, like if(x!=1): x/0 then see the output you desire..

Related

using break in try/except block doesn't exit loop at the point. why is that?

why does finally section run although I use break in else section
while 1:
try:
print(2)
except:
print("err")
else:
print("we are in else part")
break
finally:
print("we are in finally part")
both else and finally sections run once
shouldn't break exit the while loop at the point?
thanks :)
From the Python tutorial:
If the try statement reaches a break, continue or return statement, the finally clause will execute just prior to the break, continue or return statement’s execution.
This allows the finally clause to ensure that resources are released no matter how the try is exited. For instance, you might put the code to close a file in the finally clause, and it should be executed even if you break out of the loop.
Not too sure if you copy-pasted wrong but you missed an indentation. I tried
while 1:
try:
print(2)
except:
print("err")
else:
print("we are in else part")
break
finally:
print("we are in finally part")
""" (output)
2
we are in else part
we are in finally part
"""
and it worked.

Understanding Exception Handling in Python

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!

Try if Statement Breaks my print str

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.

Python: Using continue in a try-finally statement in a loop

Will the following code:
while True:
try:
print("waiting for 10 seconds...")
continue
print("never show this")
finally:
time.sleep(10)
Always print the message "waiting for 10 seconds...", sleep for 10 seconds, and do it again? In other words, do statements in finally clauses run even when the loop is continue-ed?
From the python docs:
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).
The documentation uses slightly unclear language ("on the way out") to explain how this scenario plays out. If a continue statement is executed inside of an exception clause, the code in the finally clause will be executed and then the loop will continue on to the next iteration.
Here's a very clear example that demonstrates the behavior.
Code:
i=0
while i<5:
try:
assert(i!=3) #Raises an AssertionError if i==3
print("i={0}".format(i))
except:
continue
finally:
i+= 1; #Increment i
'''
Output:
i=0
i=1
i=2
i=4
'''
Now from the latest version of python (3.8.4) , 'continue' can be used inside 'finally' blocks.enter image description here

What is the intended use of the optional "else" clause of the "try" statement in Python?

What is the intended use of the optional else clause of the try statement?
The statements in the else block are executed if execution falls off the bottom of the try - if there was no exception. Honestly, I've never found a need.
However, Handling Exceptions notes:
The use of the else clause is better
than adding additional code to the try
clause because it avoids accidentally
catching an exception that wasn’t
raised by the code being protected by
the try ... except statement.
So, if you have a method that could, for example, throw an IOError, and you want to catch exceptions it raises, but there's something else you want to do if the first operation succeeds, and you don't want to catch an IOError from that operation, you might write something like this:
try:
operation_that_can_throw_ioerror()
except IOError:
handle_the_exception_somehow()
else:
# we don't want to catch the IOError if it's raised
another_operation_that_can_throw_ioerror()
finally:
something_we_always_need_to_do()
If you just put another_operation_that_can_throw_ioerror() after operation_that_can_throw_ioerror, the except would catch the second call's errors. And if you put it after the whole try block, it'll always be run, and not until after the finally. The else lets you make sure
the second operation's only run if there's no exception,
it's run before the finally block, and
any IOErrors it raises aren't caught here
There is one big reason to use else - style and readability. It's generally a good idea to keep code that can cause exceptions near the code that deals with them. For example, compare these:
try:
from EasyDialogs import AskPassword
# 20 other lines
getpass = AskPassword
except ImportError:
getpass = default_getpass
and
try:
from EasyDialogs import AskPassword
except ImportError:
getpass = default_getpass
else:
# 20 other lines
getpass = AskPassword
The second one is good when the except can't return early, or re-throw the exception. If possible, I would have written:
try:
from EasyDialogs import AskPassword
except ImportError:
getpass = default_getpass
return False # or throw Exception('something more descriptive')
# 20 other lines
getpass = AskPassword
Note: Answer copied from recently-posted duplicate here, hence all this "AskPassword" stuff.
Python try-else
What is the intended use of the optional else clause of the try statement?
The intended use is to have a context for more code to run if there were no exceptions where it was expected to be handled.
This context avoids accidentally handling errors you did not expect.
But it's important to understand the precise conditions that cause the else clause to run, because return, continue, and break can interrupt the control flow to else.
In Summary
The else statement runs if there are no exceptions and if not interrupted by a return, continue, or break statement.
The other answers miss that last part.
From the docs:
The optional else clause is executed if and when control flows off the
end of the try clause.*
(Bolding added.) And the footnote reads:
*Currently, control “flows off the end” except in the case of an
exception or the execution of a return, continue, or break statement.
It does require at least one preceding except clause (see the grammar). So it really isn't "try-else," it's "try-except-else(-finally)," with the else (and finally) being optional.
The Python Tutorial elaborates on the intended usage:
The try ... except statement has an optional else clause, which, when
present, must follow all except clauses. It is useful for code that
must be executed if the try clause does not raise an exception. For
example:
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except OSError:
print('cannot open', arg)
else:
print(arg, 'has', len(f.readlines()), 'lines')
f.close()
The use of the else clause is better than adding additional code to
the try clause because it avoids accidentally catching an exception
that wasn’t raised by the code being protected by the try ... except
statement.
Example differentiating else versus code following the try block
If you handle an error, the else block will not run. For example:
def handle_error():
try:
raise RuntimeError('oops!')
except RuntimeError as error:
print('handled a RuntimeError, no big deal.')
else:
print('if this prints, we had no error!') # won't print!
print('And now we have left the try block!') # will print!
And now,
>>> handle_error()
handled a RuntimeError, no big deal.
And now we have left the try block!
One use: test some code that should raise an exception.
try:
this_should_raise_TypeError()
except TypeError:
pass
except:
assert False, "Raised the wrong exception type"
else:
assert False, "Didn't raise any exception"
(This code should be abstracted into a more generic test in practice.)
Try-except-else is great for combining the EAFP pattern with duck-typing:
try:
cs = x.cleanupSet
except AttributeError:
pass
else:
for v in cs:
v.cleanup()
You might think this naïve code is fine:
try:
for v in x.cleanupSet:
v.clenaup()
except AttributeError:
pass
This is a great way of accidentally hiding severe bugs in your code. I typo-ed cleanup there, but the AttributeError that would let me know is being swallowed. Worse, what if I'd written it correctly, but the cleanup method was occasionally being passed a user type that had a misnamed attribute, causing it to silently fail half-way through and leave a file unclosed? Good luck debugging that one.
I find it really useful when you've got cleanup to do that has to be done even if there's an exception:
try:
data = something_that_can_go_wrong()
except Exception as e: # yes, I know that's a bad way to do it...
handle_exception(e)
else:
do_stuff(data)
finally:
clean_up()
Even though you can't think of a use of it right now, you can bet there has to be a use for it. Here is an unimaginative sample:
With else:
a = [1,2,3]
try:
something = a[2]
except IndexError:
print("out of bounds")
else:
print(something)
Without else:
try:
something = a[2]
except IndexError:
print("out of bounds")
if "something" in locals():
print(something)
Here you have the variable something defined if no error is thrown. You can remove this outside the try block, but then it requires some messy detection if a variable is defined.
There's a nice example of try-else in PEP 380. Basically, it comes down to doing different exception handling in different parts of the algorithm.
It's something like this:
try:
do_init_stuff()
except:
handle_init_suff_execption()
else:
try:
do_middle_stuff()
except:
handle_middle_stuff_exception()
This allows you to write the exception handling code nearer to where the exception occurs.
From Errors and Exceptions # Handling exceptions - docs.python.org
The try ... except statement has an optional else clause, which,
when present, must follow all except clauses. It is useful for code
that must be executed if the try clause does not raise an exception.
For example:
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print 'cannot open', arg
else:
print arg, 'has', len(f.readlines()), 'lines'
f.close()
The use of the else clause is better than adding additional code to
the try clause because it avoids accidentally catching an exception
that wasn’t raised by the code being protected by the try ... except
statement.
try:
statements # statements that can raise exceptions
except:
statements # statements that will be executed to handle exceptions
else:
statements # statements that will be executed if there is no exception
Example :
try:
age=int(input('Enter your age: '))
except:
print ('You have entered an invalid value.')
else:
if age <= 21:
print('You are not allowed to enter, you are too young.')
else:
print('Welcome, you are old enough.')
The Output :
>>>
Enter your age: a
You have entered an invalid value.
>>> RESTART
>>>
Enter your age: 25
Welcome, you are old enough.
>>> RESTART
>>>
Enter your age: 13
You are not allowed to enter, you are too young.
>>>
Copied from : https://geek-university.com/python/the-try-except-else-statements/
Looking at Python reference it seems that else is executed after try when there's no exception.
The optional else clause is executed if and when control flows off the end of the try clause. 2 Exceptions in the else clause are not handled by the preceding except clauses.
Dive into python has an example where, if I understand correctly, in try block they try to import a module, when that fails you get exception and bind default but when it works you have an option to go into else block and bind what is required (see link for the example and explanation).
If you tried to do work in catch block it might throw another exception - I guess that's where the else block comes handy.
That's it. The 'else' block of a try-except clause exists for code that runs when (and only when) the tried operation succeeds. It can be used, and it can be abused.
try:
fp= open("configuration_file", "rb")
except EnvironmentError:
confdata= '' # it's ok if the file can't be opened
else:
confdata= fp.read()
fp.close()
# your code continues here
# working with (possibly empty) confdata
Personally, I like it and use it when appropriate. It semantically groups statements.
I would add another use case that seems straight forward when handling DB sessions:
# getting a DB connection
conn = db.engine.connect()
# and binding to a DB session
session = db.get_session(bind=conn)
try:
# we build the query to DB
q = session.query(MyTable).filter(MyTable.col1 == 'query_val')
# i.e retrieve one row
data_set = q.one_or_none()
# return results
return [{'col1': data_set.col1, 'col2': data_set.col2, ...}]
except:
# here we make sure to rollback the transaction,
# handy when we update stuff into DB
session.rollback()
raise
else:
# when no errors then we can commit DB changes
session.commit()
finally:
# and finally we can close the session
session.close()
Perhaps a use might be:
#debug = []
def debuglog(text, obj=None):
" Simple little logger. "
try:
debug # does global exist?
except NameError:
pass # if not, don't even bother displaying
except:
print('Unknown cause. Debug debuglog().')
else:
# debug does exist.
# Now test if you want to log this debug message
# from caller "obj"
try:
if obj in debug:
print(text) # stdout
except TypeError:
print('The global "debug" flag should be an iterable.')
except:
print('Unknown cause. Debug debuglog().')
def myfunc():
debuglog('Made it to myfunc()', myfunc)
debug = [myfunc,]
myfunc()
Maybe this will lead you too a use.
I have found the try: ... else: construct useful in the situation where you are running database queries and logging the results of those queries to a separate database of the same flavour/type. Let's say I have lots of worker threads all handling database queries submitted to a queue
#in a long running loop
try:
query = queue.get()
conn = connect_to_db(<main db>)
curs = conn.cursor()
try:
curs.execute("<some query on user input that may fail even if sanitized">)
except DBError:
logconn = connect_to_db(<logging db>)
logcurs = logconn.cursor()
logcurs.execute("<update in DB log with record of failed query")
logcurs.close()
logconn.close()
else:
#we can't put this in main try block because an error connecting
#to the logging DB would be indistinguishable from an error in
#the mainquery
#We can't put this after the whole try: except: finally: block
#because then we don't know if the query was successful or not
logconn = connect_to_db(<logging db>)
logcurs = logconn.cursor()
logcurs.execute("<update in DB log with record of successful query")
logcurs.close()
logconn.close()
#do something in response to successful query
except DBError:
#This DBError is because of a problem with the logging database, but
#we can't let that crash the whole thread over what might be a
#temporary network glitch
finally:
curs.close()
conn.close()
#other cleanup if necessary like telling the queue the task is finished
Of course if you can distinguish between the possible exceptions that might be thrown, you don't have to use this, but if code reacting to a successful piece of code might throw the same exception as the successful piece, and you can't just let the second possible exception go, or return immediately on success (which would kill the thread in my case), then this does come in handy.
Here is another place where I like to use this pattern:
while data in items:
try
data = json.loads(data)
except ValueError as e:
log error
else:
# work on the `data`
An else block can often exist to complement functionality that occurs in every except block.
try:
test_consistency(valuable_data)
except Except1:
inconsistency_type = 1
except Except2:
inconsistency_type = 2
except:
# Something else is wrong
raise
else:
inconsistency_type = 0
"""
Process each individual inconsistency down here instead of
inside the except blocks. Use 0 to mean no inconsistency.
"""
In this case, inconsistency_type is set in each except block, so that behaviour is complemented in the no-error case in else.
Of course, I'm describing this as a pattern that may turn up in your own code someday. In this specific case, you just set inconsistency_type to 0 before the try block anyway.
One of the use scenarios I can think of is unpredictable exceptions, which can be circumvented if you try again. For instance, when the operations in try block involves random numbers:
while True:
try:
r = random.random()
some_operation_that_fails_for_specific_r(r)
except Exception:
continue
else:
break
But if the exception can be predicted, you should always choose validation beforehand over an exception. However, not everything can be predicted, so this code pattern has its place.
I have found else useful for dealing with a possibly incorrect config file:
try:
value, unit = cfg['lock'].split()
except ValueError:
msg = 'lock monitoring config must consist of two words separated by white space'
self.log('warn', msg)
else:
# get on with lock monitoring if config is ok
An exception reading the lock config disables lock monitoring and ValueErrors log a helpful warning message.
Suppose your programming logic depends on whether a dictionary has an entry with a given key. You can test the result of dict.get(key) using if... else... construct, or you can do:
try:
val = dic[key]
except KeyError:
do_some_stuff()
else:
do_some_stuff_with_val(val)
One could use this construct for handling exceptions in a common way within the finally clause, while doing something else when there's no exception:
class TooManyRetries(RuntimeError):
pass
n_tries = 0
max_retries = 2
while True:
try:
n_tries += 1
if n_tries >= max_retries:
raise TooManyRetries
fail_prone_operation()
except Exception1 as ex:
# handle1
except Exception2 as ex:
# handle2
except Exception3 as ex:
# handle3
except TooManyRetries as ex:
raise
else: # No exception
n_tries = 0
finally:
common_restore_state()
continue
I may have missed it in the dozens of answers, but I prefer to minimize the LOC in a try: block, but I like how finally: can clean up a code segment. The else: block provides a clean way to accommodate that for file I/O, database work, etc., lots of examples above.
The else: block is confusing and (nearly) useless. It's also part of the for and while statements.
Actually, even on an if-statement, the else: can be abused in truly terrible ways creating bugs that are very hard to find.
Consider this.
if a < 10:
# condition stated explicitly
elif a > 10 and b < 10:
# condition confusing but at least explicit
else:
# Exactly what is true here?
# Can be hard to reason out what condition is true
Think twice about else:. It is generally a problem. Avoid it except in an if-statement and even then consider documenting the else- condition to make it explicit.

Categories