今天研究了下装饰器,添加重试功能遇到了个坑,跟大家分享一下;

代码如下:

 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,但是目前先记下来,日后觅得真理再来更新。