问题
I've created a bunch of functions and I need very similar except clauses in all of them, but I hate having so many lines of try and except clauses and the same code inside of each function. For example:
import sys
import random
def foo():
num=random.random()
try:
if num>0.5: print 'OK'
elif num>0.25: raise NameError('Too Small')
else: raise KeyboardInterrupt
except NameError:
print "%s had a NameError" % sys._getframe().f_code.co_name
except:
print "%s had a different Error" % sys._getframe().f_code.co_name
def bar():
num=random.random()
try:
if num>0.8: print 'OK'
elif num>0.6: raise NameError('Too Small')
else: raise KeyboardInterrupt
except NameError:
print "%s had a NameError" % sys._getframe().f_code.co_name
except:
print "%s had a different Error" % sys._getframe().f_code.co_name
The code after "try" is different for the functions, but the code after "except" is the same. I want to consolidate those except statements so they don't make my code look so cramped. Is there a good way to do this?
回答1:
Python Decorators are what you want.
You said the except block is always the same. Make a custom decorator that does what you want. You'll have to apply this to each function/method but it sure does save duplication.
def handleError(function):
def handleProblems():
try:
function()
except Exception:
print "Oh noes"
return handleProblems
@handleError
def example():
raise Exception("Boom!")
When calling a method with the decorator applied:
>>> >>> example() Oh noes >>>
You will need to change the exception types as well as what you do, but you get the jist of where I'm going with this.
回答2:
The content inside your try
block is the interesting stuff, so that should be in functions. Then just select which function you want, and call it, wrapped by your exceptions. You could even write the exception code as a function, and pass the selected function to this as an argument. e.g.
def foo():
num=random.random()
if num>0.5: print 'OK'
elif num>0.25: raise NameError('Too Small')
else: raise KeyboardInterrupt
def bar():
num=random.random()
if num>0.8: print 'OK'
elif num>0.6: raise NameError('Too Small')
else: raise KeyboardInterrupt
def try_numerics(f):
try:
f()
except NameError:
print "%s had a NameError" % sys._getframe().f_code.co_name
except:
print "%s had a different Error" % sys._getframe().f_code.co_name
# In your main code...
if (need_to_run_foo):
try_numerics(foo)
elif (need_to_run_bar):
try_numerics(bar)
回答3:
The answer above does not apply for Functions that take arguments - for the later case, I think you would want something like this:
def handleError(f):
def handleProblems(*args, **kwargs):
try:
return f(*args, **kwargs)
except Exception:
print "Oh noes"
return handleProblems
We can test it like so:
@handleError
def addTwo(x, y):
print(x + y)
>>> addTwo(5,5)
10
>>> addTwo(5, 's')
Oh noes
回答4:
If those are your actual functions it would be easy to generalize them.
You could create one general function
def general(bottom_num, top_num):
num=random.random()
try:
if num>top_num: print 'OK'
elif num>bottom_num: raise NameError('Too Small')
else: raise KeyboardInterrupt
except NameError:
print "%s had a NameError" % sys._getframe().f_code.co_name
except:
print "%s had a different Error" % sys._getframe().f_code.co_name
this would keep your code from repeating and address the try: except: issue
回答5:
I ran into the same scenario recently, in my case I have some custom exceptions based on which I need to log or raise the Exception further. I have created a decorator method to handle the exceptions as per type.
try:
obj.some_method()
except Exception as e:
catch_and_log_exception(e)
def catch_and_log_exception(e):
if isinstance(e, MyConnectionError):
print "Connection error : %s." % e.message
sys.exit(1)
elif isinstance(e, MyConnectionTimeout):
print "Connection to server has been timed out. %s" % e.message
sys.exit(1)
elif isinstance(e, MyException):
message = e.explanation if e.explanation else e.message
log_error_message(str(message))
print "Failed, please check the logs."
sys.exit(1)
else:
raise e
Hope this help !!
来源:https://stackoverflow.com/questions/9386592/repetitive-try-and-except-clauses