I really wanted a way to track my exceptions without making my code look ugly. The answer seemed to be to use Python's decorators in some way, but they introduce a twist... decorators return functions, so checking the exception information always yields an exception inside a decorator.
As an example, see the following:
import inspect
def test_handler(func):
def func2(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception, e:
print "excepted"
(file,line,fname,context,ind) =
inspect.getframeinfo(inspect.currentframe())
print "Func: %s" % (str(fname))
return func2
@test_handler
def run_user_codes():
k = {}
k['test']
if __name__ == "__main__":
print "In main"
try:
run_user_codes()
except Exception, e:
str(e)
When you run that, the output will be:
In main
excepted
Func: func2
To solve this problem, you can use the traceback module to get accurate data regarding the actual exception. For example:
import sys, traceback
class TrackException(Exception):
def __init__(self, tb=None):
self._tb = []
self._tb.append(tb)
def add_tb(self, tb):
self._tb.append(tb)
def __str__(self):
string = ""
count = 0
for t in self._tb:
(file, line, funcname, codestr) = t
string += "[%d] %s (line %d, in %s): %s\n" %
(count,file, line, funcname, codestr)
count += 1
return string
def __getitem__(self, y):
return self._tb[y]
def inspected_exception_handler(func):
def func2(*args, **kwargs):
try:
return func(*args, **kwargs)
except TrackException, e:
(t,v,tb) = sys.exc_info()
list = traceback.extract_tb(tb)
e.add_tb(list[1])
raise e
except Exception, e:
(t,v,tb) = sys.exc_info()
list = traceback.extract_tb(tb)
raise TrackException(list[1])
return func2
@inspected_exception_handler
def run_user_code():
k = {}
k['test']
@inspected_exception_handler
def func():
run_user_code()
if __name__ == "__main__":
try:
func()
except Exception, e:
print str(e)
Including the above code in your code makes tracking function exceptions much easier without cluttering your code.
No comments:
Post a Comment