两个实用的 python 装饰器: timeout超时控制 和 trace单步追踪
timeout超时控制
通过设置时钟信号给函数添加超时终端功能, 不适用于通过 os.system() 调用外部程序的情形.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
import signal import functools class TimeoutError(Exception): pass def timeout(seconds, error_message='Function call timed out'): def decorated(func): def _handle_timeout(signum, frame): raise TimeoutError(error_message) def wrapper(*args, **kwargs): signal.signal(signal.SIGALRM, _handle_timeout) signal.alarm(seconds) try: result = func(*args, **kwargs) finally: signal.alarm(0) return result return functools.wraps(func)(wrapper) return decorated @timeout(3) def slowfunc(sleep_time): import time time.sleep(sleep_time) if '__main__' == __name__: slowfunc(1) print 'ok' try: slowfunc(5) except TimeoutError: print 'timeout' |
trace单步追踪
提供类似 bash -x 调试功能, 打印执行的每一行代码.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
import os import sys import linecache def trace(f): def localtrace(frame, why, arg): if 'line' == why: # record the file name and line number of every trace filepath = frame.f_code.co_filename lineno = frame.f_lineno print '{filepath}({lineno}): {line}'.format( filepath=filepath, lineno=lineno, line=linecache.getline(filepath, lineno).strip('\r\n')) return localtrace def globaltrace(frame, why, arg): if 'call' == why: return localtrace return None def _f(*args, **kwards): sys.settrace(globaltrace) result = f(*args, **kwards) sys.settrace(None) return result return _f @trace def xxx(): print 1 result = '' for i in ['1', '2', '3']: if i == '3': result += i print result if '__main__' == __name__: xxx() |
输出示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
python2 ./test/trace.py ./test/trace.py(34): print 1 1 ./test/trace.py(36): result = '' ./test/trace.py(37): for i in ['1', '2', '3']: ./test/trace.py(38): if i == '3': ./test/trace.py(37): for i in ['1', '2', '3']: ./test/trace.py(38): if i == '3': ./test/trace.py(37): for i in ['1', '2', '3']: ./test/trace.py(38): if i == '3': ./test/trace.py(39): result += i ./test/trace.py(37): for i in ['1', '2', '3']: ./test/trace.py(41): print result 3 |
原文地址:http://www.logevery.com/python/python_two_decorate_timeout_and_trace.html