In Python's try, except blocks, why does else need to exist if I can just use an except: without a specifier?
It seems like your understanding of how try, except, else, and finally is off.
Here's a summary of how they all work together, from looking at https://docs.python.org/2/tutorial/errors.html:
try:
#Try something that might raise an exception
except <exception specifier>:
#Code here will only run if the exception that came up was the one specified
except:
#Except clause without specifier will catch all exceptions
else:
#Executed if try clause doesn't raise exception
#You can only have this else here if you also have except blocks
finally:
#Runs no matter what
Related
I have a try block case in my code and I want to ignore one particular exception and all the rest should be raised.
For example:
try:
blah
except <exception> as e:
raise Exception(e)
In this kind of case, I want all the exceptions to be raised except for one case, say if the exception is "query not found" I have to ignore it.
How do I ignore that single exception?
I can use multiple except blocks but how to define a exception?
You can give something like this:
try:
print(x)
except NameError:
print("Variable x is not defined")
except:
print("Something else went wrong")
In this case, you want to catch NameError and specify a message. For all others, you want to specify another message.
Let's say you want to ignore NameError, then you can just give continue or pass.
Alternatively, you can also raise an exception.
Example will be:
x = -1
if x < 0:
raise Exception("Sorry, no numbers below zero")
So you can use a combination of all this to get you what you want.
If you want more details on exception, see the below links:
https://docs.python.org/3/tutorial/errors.html
https://www.w3schools.com/python/python_try_except.asp
https://realpython.com/python-exceptions/
And on stack overflow (as Gino highlighted), see
Handling all but one exception
As an alternative to #Joe Ferndz's answer, in case you don't want the exception to be raised but still want the block to exit, you can use suppress from the contextlib module:
from contextlib import suppress
with suppress(ValueError):
print('hello world')
raise ValueError
print('this will not be printed')
In this case, the block still exits on raise ValueError, but an exception is not raised.
So I want to be efficient in making code in python, and I am doing something like this:
try:
#Code A
except:
#Code A
try:
#Code B
except:
#Code B
try:
#Code B
except:
#Code B
But I want to link all of them to one except block so I can use an else statement to catch em' all! (Reference intended).
So could I do something like the following?
try:
#Code A
try:
#Code B
except:
#Code C
else:
#Code D
I have tried the code, but to my self findings and limited questions that are 'similar' all I get is: Error: invalid syntax "try:". Is there anything I can do about this?
You actually don't need those extra trys at all. Whenever there's an exception raised inside the try block, all code starting there until the end of the block is skipped and the control jumps immediately to the matching except block. And as well, the else block is executed when the try block reachs its end normally. This way you don't need multiple try blocks - just concatenate them into one and you'll achieve your aim.
No you can't have multiple try block associated with only one except block. but you can have muliple except block releated to only one try block.
every try block need except block if you didn't provide one you will have an exception.
example of mulitple except block releated to one try block :-
try:
# do something
pass
except ValueError:
# handle ValueError exception
pass
except (TypeError, ZeroDivisionError):
# handle multiple exceptions
# TypeError and ZeroDivisionError
pass
except:
# handle all other exceptions
pass
suppose you perform some operation in try block and you encountered a problem then first except block will take the control if it can't handle the exception then the below except block will handle it and so on......
Note: if the first except block can handle the exception the next except block does not execute or will not come in action.
It is always good practice to have more generic except block for a specific exception type.
a single try statement with multiple except block
try:
#put your risky code
# put another risky code
pass
# multiple exception block will help to catch exact exception and can perform
# operation
except KeyError:
pass
except IOError:
pass
except ValueError:
pass
except Exception:
pass
else:
pass
In what I have written, NoResultException can be raised either in my try block or my except UnexpectedAlertPresentException block. I would like to go to the except NoResultException block in either case, but it only does this if NoResultException is raised in the try block. This is approximately what I have now:
try:
# do things
except UnexpectedAlertPresentException:
# do other things, including possibly raise NoResultException
except NoResultException:
# handle exception
I could change it to something like this:
try:
# do things
except UnexpectedAlertPresentException:
try:
# do other things, including possibly raise NoResultException
except NoResultException:
# handle exception
except NoResultException:
# handle exception
to handle NoResultException, but I'm trying to avoid repeating myself. Is there any better way to do this?
try:
try:
# do things
except UnexpectedAlertPresentException:
# do other things, including possibly raise NoResultException
except NoResultException:
# handle exception
Try not to go overboard with the exception-handling control flow. The logic can get really hard to reason about, and the indentation can get really deep.
I have this kind of code:
try:
return make_success_result()
except FirstException:
handle_first_exception()
return make_error_result()
except SecondException:
handle_second_exception()
return make_error_result()
And I'm wondering is there any way I can achieve this:
try:
# do something
except Error1:
# do Error1 specific handling
except Error2:
# do Error2 specific handling
else:
# do this if there was no exception
????:
# ALSO do this if there was ANY of the listed exceptions (e.g. some common error handling)
So the code is executed in one of following sequences:
try > else > finally
try > except > ???? > finally
EDIT: my point here is that ???? block should execute right after ANY of the except blocks, meaning that it's an addition to error handling, not a substitution.
What I would do in that case is to set a boolean when you get an exception, like so:
got_exception = False
try:
# do something
except Error1:
# do Error1 specific handling
got_exception = True
except Error2:
# do Error2 specific handling
got_exception = True
else:
# If there was no exception
finally:
if got_exception:
# ALSO do this if there was ANY exception (e.g. some common error handling)
This should fit your needs, which is IMO the cleanest way of combining all of the solutions which have been presented into the most readable code structure that's going to be the easiest to debug.
You can actually do this:
try:
print 'try'
# 1/0
# {}[1]
# {}.a
except AttributeError, KeyError: # only handle these exceptions..
try:
raise # re-raise the exception so we can add a finally-clause executing iff there was an exception.
except AttributeError:
print 'attrerr'
# raise ... # any raises here will also execute 'common'
except KeyError:
print 'keyerror'
finally: # update 0: you wanted the common code after the exceptions..
print "common"
else:
print 'no exception'
but it is horrid and I would not suggest that you do without copious amounts of comments describing why..
UPDATE: you don't need to catch anything but the interesting exceptions in the inner try-block. Code updated.
UPDATE2: per OP's clarification, common should just be executed when an interesting exception is thrown. Code updated. #MattTaylor's version is definitely the way to go ;-)
Yes, exception handling in python includes both an else and a finally clause. You can do this:
try:
# do something
except Error1:
# do Error1 specific handling
except Error2:
# do Error2 specific handling
else:
# do this if there was no exception
finally:
# Do this in any case!
The python docs mention these blocks, even though it doesn't show the full example you need.
EDIT:
I see that you do not ask specifically for the clean-up in the general case. Python docs put it this way:
The try statement has another optional clause which is intended to define clean-up actions that must be executed under all circumstances.
Note that the finally will run whether there was an exception or not. Combined with the else block, you should still be able to do what you want.
You could trap all errors and check for its type in the error handling code like this:
try:
# do something
except Exception as e:
if isinstance(e, Error1):
# do Error1 specific handling
elif isinstance(e, Error2):
# do Error2 specific handling
else:
# do non-Error1/Error2 handling
# ALSO do this if there was ANY exception (e.g. some common error handling)
else:
# do this if there was no exception
I have some code which represents a test case within a proprietary testing framework that looks something like this:
def test_alarm(self):
self.setup_some_test_data()
try:
self.send_alarm_message()
except:
print "Unexpected error:", sys.exc_info()
finally:
self.teardown_some_test_data()
I've been told to drop the print as it's not necessary and the test framework will in any case catch any exceptions, which is preferred to catching them here, but I still need to always clear the data down, as in the finally block.
Do I just drop the except block entirely? Alternatively, how, can I structure the code to effectively have an empty except block and retain the finally? Is this good practice in Python or is there a better way to do it?
Edit Note that I did try just dropping the except block entirely, and I had no obvious run-time problems, though since exceptions are unlikely in the the call to send_alarm_message(), it was unclear to me how it would work if an exception was thrown or whether this was considered good practice by the Python community.
Either drop the except Block, or improove it really by adding
except [Exception-Class]:
pass
where [Exception-Class] is the exception to be excepted. This adds some sugar on it, because really unexpected Errors are not getting catched by this. (Or add this as a seperate:
except Exception, ex:
print "Unexpected error:", ex
Yes, you can drop the except block completely, it is a valid python syntax to have just try and finally . Example -
In [58]: try:
....: print("Blah")
....: finally:
....: print("halB")
....:
Blah
halB
Please note this will not catch any Exceptions/Errors that occur within the try block, and I am guessing that is what you want.
I have seen this used at quite some places, where we are creating some variables/resources that need to be cleared irrespective of whether any exceptions/errors occur, but we do not want to handle any Exceptions at that particular place.
If you don't want to do anything in except block, then you can pass it.
try:
self.send_alarm_message()
except:
pass
finally:
self.teardown_some_test_data()