【问题标题】:Python trace module - Trace lines as they are executed, but save to file, rather than stdoutPython 跟踪模块 - 在执行时跟踪行,但保存到文件,而不是标准输出
【发布时间】:2011-05-16 06:15:42
【问题描述】:

我想在执行 python 脚本时跟踪它们的行。但是我使用的程序需要将内容打印到标准输出。 python 跟踪模块的跟踪选项将它们打印到标准输出。有没有办法告诉它不要将它们打印到标准输出,而是将它们保存到文件中?我尝试设置outfile 参数,但它并没有停止打印跟踪线。

【问题讨论】:

    标签: python stdout trace


    【解决方案1】:

    您可以复制跟踪模块代码,并进行一些更改以使其输出写入您选择的文件。在第 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)),
    

    【讨论】:

    • 万一这崩溃了,你应该启用line-bufferingopen(..., buffering=1)
    【解决方案2】:

    根据跟踪模块的文档,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

    【讨论】:

    • 是否有/其他模块可以将跟踪数据保存到文件中?
    • @Rory:你是如何追踪执行的?你用的是什么命令行?我之前使用过手动跟踪,根据自己的喜好修改输出。
    • 感谢您的回答。这是很多代码。是否有维护的库可以在这里提供帮助?
    【解决方案3】:

    您可能需要所谓的“功能跟踪”described for PHP。我创建了Python tool,它使用 pyfunc sys.settrace() 钩子提到的产生类似的输出。

    【讨论】:

      【解决方案4】:

      您是否在命令行调用跟踪?如果是这样,我建议使用将任何标准输出重新路由到任何文件的标准方法。 Redirect all output to file

      foo > allout.txt 2>&1
      

      如果你在 windows 中,我相信 windows 也有类似的东西。

      【讨论】:

      • 我认为 OP 希望程序自己的标准输出仍然可以到通常的位置。
      【解决方案5】:

      当您将 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

      【讨论】:

        猜你喜欢
        • 2022-01-27
        • 2022-07-09
        • 1970-01-01
        • 2011-02-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多