好。所以,我的问题可能有点模糊。这就是我想要做的事情:
我已经继承了'大量的python脚本,我应该调试,记录和改进它们。目前还没有很多文档可供使用。在几乎所有情况下,我都知道输入数据和输出数据需要什么。
我的计划是将原始函数包装在装饰器函数周围,并将输出记录在文本文件中,同时不中断正常的程序流程。我也不想暂时搞乱原始源代码。所以,这是装饰器的代码:
def printoutput(func):
"""Decorator function to write the values of a function to a log file
1. If the output is a tuple or a list then the output will get written as Output1: .. , Output2:.. etc.
2. If the output is anything else, it will get written once.
"""
import time
#Accesfunc passes arguments to a calls the actual function. It also logs data.
def accessfunc(*args,**kwargs):
#Call the function with any number of arguments and keyword arguments.
y = func(*args,**kwargs)
#Save the name of the function being called.
funcname = r"D:\{}_{}_output.txt".format(time.time(), func.__name__)
#Create a file for logging data, specific to a function.
with open(funcname,'w') as fileoutput:
#if the output returned by the function is a lsit or tuple then log those on separate lines.
if isinstance(y,(tuple,list)):
for idx,outputs in enumerate(y):
fileoutput.write("Output{}:".format(idx))
fileoutput.write(str(outputs)+"\n")
#if the output is a single entity like a string or a number then log it on a single line.
else:
fileoutput.write("Output:\n")
fileoutput.write(str(y))
return y
return accessfunc
我的问题是:
有没有更好的方法来完成我想要做的事情?
我正在记录函数的名称,有没有办法我也可以记录返回的变量的名称。例如,如果函数A返回B,我可以以这样的方式记录它,即" A"和" B"在我的日志文件中提到?
答案 0 :(得分:1)
有sys.settrace
可以向您显示很多内容而无需修改任何内容。
http://pymotw.com/2/sys/tracing.html
这是对其中一个示例的略微修改,它们在执行函数之前从堆栈帧中抓取局部变量,其中包含参数。
import sys
def trace_calls_and_returns(frame, event, arg):
co = frame.f_code
func_name = co.co_name
if func_name == 'write':
# Ignore write() calls from print statements
return
line_no = frame.f_lineno
filename = co.co_filename
if event == 'call':
print 'Call to %s(%s) on line %s of %s' % (func_name, frame.f_locals, line_no, filename)
return trace_calls_and_returns
elif event == 'return':
print '%s() => %s' % (func_name, arg)
return
def times(a,b):
foo = "what"
return a*b
def x(a):
return times(a,a)
def y(a):
return times(a,2)
sys.settrace(trace_calls_and_returns)
foo=x(x(y(x(2))))
输出:
Call to x({'a': 2}) on line 24 of C:/Users/cjd/Desktop/dfdfdfdf.py
Call to times({'a': 2, 'b': 2}) on line 20 of C:/Users/cjd/Desktop/dfdfdfdf.py
times() => 4
x() => 4
Call to y({'a': 4}) on line 27 of C:/Users/cjd/Desktop/dfdfdfdf.py
Call to times({'a': 4, 'b': 2}) on line 20 of C:/Users/cjd/Desktop/dfdfdfdf.py
times() => 8
y() => 8
Call to x({'a': 8}) on line 24 of C:/Users/cjd/Desktop/dfdfdfdf.py
Call to times({'a': 8, 'b': 8}) on line 20 of C:/Users/cjd/Desktop/dfdfdfdf.py
times() => 64
x() => 64
Call to x({'a': 64}) on line 24 of C:/Users/cjd/Desktop/dfdfdfdf.py
Call to times({'a': 64, 'b': 64}) on line 20 of C:/Users/cjd/Desktop/dfdfdfdf.py
times() => 4096
x() => 4096
Call to flush_stdout({}) on line 219 of C:\Python27\lib\idlelib\run.py
flush_stdout() => None
Call to put({'item': (119, None), 'self': <Queue.Queue instance at 0x0000000002B42AC8>, 'block': True, 'timeout': None}) on line 107 of C:\Python27\lib\Queue.py
Call to _put({'item': (119, None), 'self': <Queue.Queue instance at 0x0000000002B42AC8>}) on line 204 of C:\Python27\lib\Queue.py
答案 1 :(得分:0)
在我的情况下,装饰器用于缓存或方便。
对于日志记录,python的内置日志记录非常方便。
配置记录
logging.config.dictConfig(config.LOGGING)
config.LOGGING类似于: Python Logging Config
使用记录
import logging
logger = logging.getLogger(__name__)
logger.info('This is a info log.')
在我看来,日志应该存在于你的代码中,它是一种记录,它应该是明确的,如Python-Zen所说。因此,我不建议装饰人员进行伐木。