跟踪文件路径和行号 [英] Tracing fIle path and line number

查看:75
本文介绍了跟踪文件路径和行号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用python的trace模块来跟踪一些代码.当我以这种方式跟踪代码时,可以获得以下两个结果之一:

I'm using python's trace module to trace some code. When I trace code this way, I can get one of the following two results:

致电:

tracer = trace.Trace(count=False, trace=True, ignoredirs=[sys.prefix, sys.exec_prefix])
r = tracer.run('run()')
tracer.results().write_results(show_missing=True)

结果:

<filename>(<line number>): <line of code>

致电 [引用]:

tracer = trace.Trace(count=False, trace=True, ignoredirs=[sys.prefix, sys.exec_prefix], countfuncs=True)
r = tracer.run('run()')
tracer.results().write_results(show_missing=True)

结果:

filename:<filepath>, modulename:<module name>, funcname: <function name>

我真正需要的是能给我带来帮助的痕迹:

What I really need is a trace that gives me this:

<filepath> <line number>

似乎我可以使用上面的信息并对其进行交织以获得所需的信息,但是在以下用例中,这样的尝试将失败:

It would seem that I could use the above information and interleave them to get what I need, but such an attempt would fail in the following use case:

  • sys.path包含目录A和目录B.
  • 有两个文件A/foo.pyB/foo.py
  • A/foo.pyB/foo.py都包含在第100-120行中定义的函数bar
  • A/foo.pyB/foo.py
  • 之间有一些细微差别
  • sys.path contains directory A and directory B.
  • There are two files A/foo.py and B/foo.py
  • Both A/foo.py and B/foo.py contain the function bar, defined on lines 100 - 120
  • There are some minor differences between A/foo.py and B/foo.py

在这种情况下,如果不静态分析每个bar中的代码,就不可能使用这种交织来正确识别哪个bar被调用(如果我错了,请纠正我),这对于非bar本身是非常困难的.琐碎的功能.

In this scenario, using such interleaving to correctly identifying which bar is called is impossible (please correct me if I'm wrong) without statically analyzing the code within each bar, which itself is very difficult for non-trivial functions.

那么,如何获得所需的正确跟踪输出?

So, how can I get the correct trace output that I need?

推荐答案

使用一些猴子补丁,实际上很容易.深入研究trace模块的源代码,似乎在每个执行步骤中都使用了回调报告. Trace.run的基本功能(已大大简化)是:

With a little monkey-patching, this is actually quite easy. Digging around in the source code of the trace module it seems that callbacks are used to report on each execution step. The basic functionality of Trace.run, greatly simplified, is:

sys.settrace(globaltrace)   # Set the trace callback function
exec function               # Execute the function, invoking the callback as necessary
sys.settrace(None)          # Reset the trace

globaltraceTrace.__init__中定义,具体取决于传递的参数.具体来说,对于第一个示例中的参数,Trace.globaltrace_lt用作全局回调,它对执行的每一行都调用Trace.localtrace_trace.更改它只是修改Trace.localtrace的一种情况,因此要获得所需的结果:

globaltrace is defined in Trace.__init__ depending on the arguments passed. Specifically, with the arguments in your first example, Trace.globaltrace_lt is used as the global callback, which calls Trace.localtrace_trace for each line of execution. Changing it is simply a case of modifying Trace.localtrace, so to get the result you want:

import trace
import sys
import time
import linecache

class Trace(trace.Trace):
    def localtrace_trace(self, frame, why, arg):
        if why == "line":
            # record the file name and line number of every trace
            filename = frame.f_code.co_filename
            lineno = frame.f_lineno

            if self.start_time:
                print '%.2f' % (time.time() - self.start_time),
            print "%s (%d): %s" % (filename, lineno,
                                  linecache.getline(filename, lineno)),
        return self.localtrace


tracer = Trace(count=False, trace=True, ignoredirs=[sys.prefix, sys.exec_prefix])
r = tracer.run('run()')

您给出的两个示例之间有区别;如果第一个输出在Trace.run调用期间打印,第二个输出在write_results期间打印.我上面给出的代码遵循前者的模式,因此tracer.results().write_results()是不必要的.但是,如果要操纵此输出,则可以通过以类似方式修补trace.CoverageResults.write_results方法来实现.

There is a difference between the two examples you give; if the first the output is printed during the Trace.run call, in the second it is printed during write_results. The code I've given above follows the pattern of the former, so tracer.results().write_results() is not necessary. However, if you want to manipulate this output instead it can be achieved by patching the trace.CoverageResults.write_results method in a similar manner.

这篇关于跟踪文件路径和行号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆