【发布时间】:2011-05-16 06:15:42
【问题描述】:
我想在执行 python 脚本时跟踪它们的行。但是我使用的程序需要将内容打印到标准输出。 python 跟踪模块的跟踪选项将它们打印到标准输出。有没有办法告诉它不要将它们打印到标准输出,而是将它们保存到文件中?我尝试设置outfile 参数,但它并没有停止打印跟踪线。
【问题讨论】:
我想在执行 python 脚本时跟踪它们的行。但是我使用的程序需要将内容打印到标准输出。 python 跟踪模块的跟踪选项将它们打印到标准输出。有没有办法告诉它不要将它们打印到标准输出,而是将它们保存到文件中?我尝试设置outfile 参数,但它并没有停止打印跟踪线。
【问题讨论】:
您可以复制跟踪模块代码,并进行一些更改以使其输出写入您选择的文件。在第 600 行和第 650 行之间有五个 print 语句是您要更改的语句。由于您不需要让它太漂亮,您可以将其添加到文件的最后:
my_out_file = open("/home/mytrace.txt", "w")
并更改打印语句:
print "%s(%d): %s" % (bname, lineno,
linecache.getline(filename, lineno)),
变成这样:
print >>my_out_file, "%s(%d): %s" % (bname, lineno,
linecache.getline(filename, lineno)),
【讨论】:
open(..., buffering=1)
根据跟踪模块的文档,outfile 仅用于写入更新的计数信息。
Trace 模块将继续将跟踪信息打印到标准输出。
对于手动跟踪,如果有入口函数,我已经使用 sys.settrace 来完成跟踪调用流的工作。它可以扩展到逐行跟踪执行。您始终可以将信息归档到文件中,而不是将其打印到标准输出。
一个简单的结构是
import sys
import os
import linecache
trace_depth = 0
def trace(f):
def globaltrace(frame, why, arg):
global trace_depth
if why == "call":
# function call event , extract information
.....
pass
trace_depth = trace_depth + 1
return None
def localtrace(frame, why, arg):
global trace_depth
if why == "line":
# line execution event
pass
elif why == "return":
trace_depth = trace_depth - 1
# function return event
return localtrace
def _f(*args, **kwds):
sys.settrace(globaltrace)
result = f(*args, **kwds)
sys.settrace(None)
return result
return _f
globaltrace 和 localtrace 是随事件调用的回调函数 - “为什么”
调用函数时的事件,可以从框架细节中提取信息。
if why == "call":
# Parent frame details
p_func = frame.f_back.f_code.co_name
p_file = frame.f_back.f_code.co_filename
p_lineinfo = frame.f_back.f_lineno
我已经发布了完整的详细信息here。
【讨论】:
您可能需要所谓的“功能跟踪”described for PHP。我创建了Python tool,它使用 pyfunc sys.settrace() 钩子提到的产生类似的输出。
【讨论】:
您是否在命令行调用跟踪?如果是这样,我建议使用将任何标准输出重新路由到任何文件的标准方法。 Redirect all output to file
foo > allout.txt 2>&1
如果你在 windows 中,我相信 windows 也有类似的东西。
【讨论】:
当您将 stdout/stderr 用于其他用途时,另一种可能性是启动 thread 以向 queue 写入和提供消息
import threading
from queue import Queue
def worker(Q, file_dest):
with open(file_dest, "r+", buffering=1) as fh:
while True:
fh.write(f"{}\n".format(Q.get()))
...
dest_file = "some-writeable/path.txt"
Q = Queue() # can be a global, but please name it better!
t = threading.Thread(
worker,
args=(Q, dest_file),
daemon=True, # don't block exit
)
# set t.daemon = True here instead in earlier Python
t.start()
只要你想写,就用.put()方法
Q.put("some message")
buffering=1 用于line-buffering
【讨论】: