今天研究了下装饰器,添加重试功能遇到了个坑,跟大家分享一下;
代码如下:
1 def re_try(maxtry): 2 print locals() 3 def wrapper(fn): 4 print locals() 5 def _wrapper(*args, **kwargs): 6 print locals() 7 while maxtry > 0: 8 try: 9 return fn(*args, **kwargs) 10 except Exception as e: 11 print e.message 12 maxtry -= 1 13 return _wrapper 14 return wrapper 15 16 @re_try(4) 17 def test(a, b): 18 # return a+b 19 if DEC == 2: 20 return a+b 21 else: 22 raise WrapException 23 24 def main(): 25 print test(3,5) 26 27 if __name__ == '__main__': 28 main()
运行的结果如下:
{'maxtry': 4} {'fn': <function test at 0x024B5170>} {'args': (3, 5), 'fn': <function test at 0x024B5170>, 'kwargs': {}} Traceback (most recent call last): File "D:\myGit\test\testWrapp.py", line 58, in <module> main() File "D:\myGit\test\testWrapp.py", line 55, in main print test(3,5) File "D:\myGit\test\testWrapp.py", line 17, in _wrapper while maxtry > 0: UnboundLocalError: local variable 'maxtry' referenced before assignment
按道理maxtry这个变量会一直存在再整个装饰器运行过程中,但是我们看到在第4行 和第6 行并没有看到该变量,本农百思不得七姐,于是就瞎调试,终于实现了功能。
1 def re_try(max_try): 2 print locals() 3 def wrapper(func): 4 print locals() 5 @wraps(func) 6 def _wrapper(*args, **kw): 7 print locals() 8 for i in xrange(max_try): 9 try: 10 res = func(*args, **kw) 11 if res is None: 12 continue 13 else: 14 return res 15 except Exception as e: 16 print e.message 17 return _wrapper 18 return wrapper 19 20 @re_try(4) 21 def test(a, b): 22 # return a+b 23 if DEC == 2: 24 return a+b 25 else: 26 raise WrapException 27 28 def main(): 29 print test(3,5) 30 31 if __name__ == '__main__': 32 main()
把while 循环改成了for循环,得到如下运行结果:
{'max_try': 4} {'max_try': 4, 'func': <function test at 0x02613170>} {'args': (3, 5), 'kw': {}, 'func': <function test at 0x02613170>, 'max_try': 4}
虽然目前还不知道为什么装饰器内部函数里面不能使用while,但是目前先记下来,日后觅得真理再来更新。