What's the difference between "KeyError" and "KeyError as e"? - python

When writing try/except statements, whether I use
except KeyError:
or
except KeyError as e:
I get the same result.
What is the difference between the two? Is KeyError as e just more specific/custom?

When using except KeyError as e:, you can access the exception and its attributes as an object with e. Like so:
def test_function():
try:
do_something_that_fails()
except Exception as e:
print e.message, e.args
It will help with debugging any problems you have when the exception is thrown.
You can find more information on how this works in the Python Documentation.
Good luck!

Related

How to ignore one particular exception in Python?

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.

`try ... except not` construction

Recently I met an example of code I've never seen before:
try:
# a simple bunch of code
if sample == 0:
return True
else:
raise ExampleError()
except not ExampleError:
raise AnotherExampleError()
How does it work (if it works at all)?
EDIT: The answer below was for Python 3, I didn't realise the question related to Python 2.7. in Python 2, as it seems, the interpreter does not complain if the expression after except does not result in a subtype of BaseException. However, the behavior is still wrong, it will just ignore that except block in all cases.
That's a funny construction that is syntactically valid but semantically wrong. I suppose the author of the code meant to express something like "run this except block for any exception type but ExampleError". However, what is really happening is more like:
try:
# ...
except (not bool(ExampleError)):
# ...
When an exception is raised in the try block, Python goes through the different except blocks looking for one that matches the exception type. When it sees except not ExampleError, equivalent to except (not bool(ExampleError)), it results in except False, which is invalid because False is not a subtype of BaseException (or a tuple of subtypes of BaseException). So the code may even run if no exceptions are raised but is wrong.
This is not going to be successful on any version of Python as far as I know. Because the not operator always results in a Boolean value (True or False) this is trying to catch one of those values here, in this case False. Since you can't throw True or False there's no use for this.
I think the intent of the author was something like this:
try:
raise ExampleError()
except ExampleError e:
throw e
except:
raise AnotherExampleError()
A quick test shows that the code will throw a TypeError if it reaches that line:
try:
raise BaseException
except not BaseException:
print("Test1")
except BaseException:
print("Test2")
Exception:
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "main.py", line 3, in
except not BaseException: TypeError: catching classes that do not inherit from BaseException is not allowed

Handling Exceptions in Python 3.6

I am trying to handle exceptions in Python 3.6. I want to handle every possible exception and print the exception. When i do
try:
raise RuntimeError("Test")
except:
e = sys.exc_info()[0]
print(e)
it just prints
class '_mysql_exceptions.OperationalError'
How do i get the message of the Exception? In this case i would like the output to be "Test".
You can catch and print the Exception as follows:
try:
raise RuntimeError("Test")
except Exception as e:
print(e)
# Test
I'm not quite sure why you're trying to catch every Exception though, it would seem more prudent to let Python handle and raise these for you in general. Normally you would only catch specific Exceptions.
This behavior is not specific to Python 3.6.

Create custom exceptions?

Is there a way to shorten the following scenario so i don't have to use an ugly nested try except statement?
class Error(Exception):
def __init__(self):
print("That did not work")
try:
try:
gblgbl
except:
raise Error
except Error:
pass
What i want can be described as following pseudo code:
Try something:
something
if something went wrong:
raise Error
catch Error:
what to do if error occours
I don't want to raise the error if the try statement succeeds, however if i raise an exception in the exception statement like this:
try:
gblgbl
except:
raise Error
except Error:
pass
it can't be caught with an other except, since there is already an except that caught the python exception and the interpreter throws a SyntaxError.
Am i missing something obvious?
I'm aware that you probably would never use this in an actual program, but i'm curious about the theory.
There is no reason to use an exception here. The following (pseudo-)code achieves the same thing.
try:
gblgbl
except:
pass
Note however that it generally is a bad idea to catch all exceptions, since for instance the KeyboardInterrupt Exception will also be caught and the program can thus not be interrupted using Ctrl-c
Create custom exceptions?
The Python Tutorial has a section on User-defined Exceptions

try-except block: analogue for 'else' if exception was raised

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

Categories

Resources