If I name an exception as a variable, what properties are held by that variable? For example,
try:
None.nonexistent_function()
#return an AttributeError.
except Exception as ex:
self.assertEqual(__, ex.__class__.__name__)
In this instance, what is necessary to make the assertion True? How can the Name and Class of the Exception be determined?
This question is part of Python Koans, a recent port of Ruby Koans.
Try it at the REPL:
>>> try: None.foo()
... except Exception as ex: pass
...
>>> # ex is still in scope, so we can play around with it and find out for ourselves:
... ex.__class__.__name__
'AttributeError'
>>>
Hmmm... using Python's command line, I get:
>>> try:
... None.nonexistent_function()
... #return an AttributeError.
... except Exception as ex:
... print ex.__class__.__name__
...
AttributeError
>>>
So let's try:
>>> try:
... None.nonexistent_function()
... #return an AttributeError.
... except Exception as ex:
... print 'AttributeError' == ex.__class__.__name__
...
True
I don't have whatever your self object is handy, so you'll have to test the rest. Does that work for you?
Related
django's auth middleware has this code:
def get_user(request):
"""
Returns the user model instance associated with the given request session.
If no user is retrieved an instance of `AnonymousUser` is returned.
"""
from .models import AnonymousUser
user = None
try:
user_id = request.session[SESSION_KEY]
backend_path = request.session[BACKEND_SESSION_KEY]
except KeyError:
pass
else: # <------ this doesnot have if-part, but how is it meant to work?
if backend_path in settings.AUTHENTICATION_BACKENDS:
# more code...
the else part is interesting, it doesnot have if-part, what is this? really cool thing if I dont know this yet
The else forms the else part of try except
try:
user_id = request.session[SESSION_KEY]
backend_path = request.session[BACKEND_SESSION_KEY]
except KeyError:
pass
else:
if backend_path in settings.AUTHENTICATION_BACKENDS:
# more code...
The 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.
That is here it would be executed only if the code doesn't raise any KeyErrors
Example
Consider we have a dictionary as
>>> a_dict={"key" : "value"}
We can use try except to handle a KeyError as
>>> try:
... print a_dict["unknown"]
... except KeyError:
... print "key error"
...
key error
Now, we need to check if a key error occurs and if not, the else clause is executed as
>>> try:
... print a_dict["key"]
... except KeyError:
... print "key error"
... else:
... print "no errors"
...
value
no errors
Where as if any of the except clause is raised, then it won't be executed.
>>> try:
... print a_dict["unkown"]
... except KeyError:
... print "key error"
... else:
... print "no errors"
...
key error
Is it correct to call that function in some exceptions ?
Is that process correct ? Is it better to process each exceptions ?
def close_all():
try:
ftp.close()
except:
pass
try:
tar.close()
except:
pass
try:
savelist.close()
except:
pass
try:
os.remove(tarname)
except:
pass
exit()
Thanks in advance.
I think you should handle each exception one by one. This will shorten your code. First of all note all the exceptions that ftp.close() and other methods will raise. Then handle them one by one.
Example:
>>> a = 5 # a is an integer
>>> b = "Bingo" # b is a string
>>>
>>> def add_five():
try:
c + 5 # c is not defined. NameError exception is raised
except NameError:
b + 5 # b is a string. TypeError exception is raised
except TypeError:
a + 5 # a is int. No exception is raised
except:
# This last except clause is just in case you forgot to handle any exception
pass
>>>
As an experiment, I tried catching a failed assertion.
try: assert 1==2
except Exception as e: print e
Why is nothing displayed?
>>> try: assert 1==2
... except Exception as e: print type(e)
...
<type 'exceptions.AssertionError'>
or
>>> try: assert 1==2, "They Are Not Equal!!"
... except Exception as e: print e
...
They Are Not Equal!!
as to why: it is calling the __str__ method of the exception when you call print... since you did not put any text there, your text is the empty string... which is what's printed.
I'm writing a custom logging system for a project. If a function throws an exception, I want to log its local variables. Is it possible to access the raising function's local variables from the except block that caught the exception? For example:
def myfunction():
v1 = get_a_value()
raise Exception()
try:
myfunction()
except:
# can I access v1 from here?
It's generally cleaner design to pass the value to the exception, if you know that your exception handling code is going to need it. However, if you're writing a debugger or something like that, where you will need to access variables without knowing which ones they are in advance, you can access an arbitrary variable in the context where the exception was thrown:
def myfunction():
v1 = get_a_value()
raise Exception()
try:
myfunction()
except:
# can I access v1 from here?
v1 = inspect.trace()[-1][0].f_locals['v1']
The functionality of the trace function, and the format of the traceback objects it deals with, are described in the inspect module documentation.
You can look up the local variables in the frame object, which you can get from sys.exc_info.
>>> import sys
>>> def f(a):
... b = a - 1
... print 1.0 / b
...
>>> try:
... f(1)
... except Exception, e:
... print sys.exc_info()[2].tb_next.tb_frame.f_locals
...
{'a': 1, 'b': 0}
You'll have to include the appropriate number of tb_nexts depending on from how deep in the stack the exception was thrown.
def myFunction()
v1 = get_a_value()
raise Exception(v1)
try:
myFunction()
except Exception, e:
v1 = e.args[0]
Yes, if it's your own exception type. Like this:
>>> class MyExn(Exception):
... def __init__(self, val):
... self.val = val
... def __str__(self):
... print "something wrong with:", str(self.val)
...
>>> def foo():
... val = 42
... raise MyExn(val)
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in foo
__main__.MyExnsomething wrong with: 42
>>> # Or in a try block:
>>> try:
... foo()
... except MyExn as e:
... print e.val
...
42
>>>
try:
myfunction()
except:
import sys
type, value, tb = sys.exc_info()
while tb.tb_next:
tb = tb.tb_next
frame = tb.tb_frame
print frame.f_locals['v1']
Useful for "handling" exceptions without using raise Exception(some_def_var) and also without using a library such as "inspect", for example.
However, I think if is to handle the exception "in real", might be better to use something like raise Exception(some_def_var). See #capfredf answer.
class MyClass():
def __init__(self):
self.my_attr_I = ""
self.my_attr_II = ""
def my_def_I(self):
try:
self.my_def_II()
except Exception as e:
print(self.my_attr_I)
print(self.my_attr_II)
def my_def_II(self):
self.my_attr_I = "TO EXCEPT I"
self.my_attr_II = "TO except II"
# NOTE: We will treat it as a general exception! By Questor
zero_division = 1/0
I've been working in Python and ran into something that must be a common occurrence.
I have five statements that all fall into a common pitfall of raising
FooException and BarException. I want to run each of them, guarding against
these exceptions but continuing to process even if an exception is raised after
some handling is done. Now, I could do this like so:
try:
foo()
except (FooException, BarException):
pass
try:
bar()
except (FooException, BarException):
pass
try:
baz()
except (FooException, BarException):
pass
try:
spam()
except (FooException, BarException):
pass
try:
eggs()
except (FooException, BarException):
pass
but that is really verbose and in extreme violation of DRY. A rather brute-force
and obvious solution is something like this:
def wish_i_had_macros_for_this(statements, exceptions, gd, ld):
""" execute statements inside try/except handling exceptions with gd and ld
as global dictionary and local dictionary
statements is a list of strings to be executed as statements
exceptions is a list of strings that resolve to Exceptions
gd is a globals() context dictionary
ld is a locals() context dictionary
a list containing None or an Exception if an exception that wasn't
guarded against was raised during execution of the statement for each
statement is returned
"""
s = """
try:
$STATEMENT
except (%s):
pass
""" % ','.join(exceptions)
t = string.Template(s)
code = [t.substitute({'STATEMENT': s}) for s in statements]
elist = list()
for c in code:
try:
exec c in gd, ld
elist.append(None)
except Exception, e:
elist.append(e)
return elist
With usage along the lines of:
>>> results = wish_i_had_macros_for_this(
['foo()','bar()','baz','spam()','eggs()'],
['FooException','BarException'],
globals(),
locals())
[None,None,None,SpamException,None]
Is there a better way?
def execute_silently(fn, exceptions = (FooException, BarException)):
try:
fn()
except Exception as e:
if not isinstance(e, exceptions):
raise
execute_silently(foo)
execute_silently(bar)
# ...
# or even:
for fn in (foo, bar, ...):
execute_silently(fn)
What about this?
#!/usr/bin/env python
def foo():
print "foo"
def bar():
print "bar"
def baz():
print "baz"
for f in [foo, bar, baz]:
try:
f()
except (FooException, BarException):
pass
This version allows statement execution as well:
from contextlib import contextmanager
from functools import partial
#contextmanager
def exec_silent(exc=(StandardError,)):
try:
yield
except exc:
pass
silent_foobar = partial(exec_silent, (FooException, BarException))
with silent_foobar():
print 'foo'
foo()
with silent_foobar():
print 'bar'
bar()