Aiv*_*var 6 python debugging trace
在内部跟踪功能,调试函数调用时,是否可以以某种方式检索调用表达式?
我可以从traceback对象中调用行号,但如果该行上有多个函数调用(可能是相同的函数)(例如,作为更大表达式中的子表达式),那么我怎样才能知道这个调用的来源?即使从源线的起点偏移,我也会很高兴.
traceback.tb_lasti 似乎给出了更多的粒度上下文(尝试了最后一个字节码的索引) - 是否有可能将字节码连接到其确切的源范围?
编辑:只是为了澄清 - 我需要从调用源代码行中提取特定的(子)表达式(调用点).
回溯帧也有一个行号:
lineno = traceback.tb_lineno
Run Code Online (Sandbox Code Playgroud)
您还可以访问代码对象,该对象具有名称和文件名:
name = traceback.tb_frame.f_code.co_name
filename = traceback.tb_frame.f_code.co_filename
Run Code Online (Sandbox Code Playgroud)
您可以使用文件名和行号,以及帧全局和linecache模块来有效地将其转换为正确的源代码行:
linecache.checkcache(filename)
line = linecache.getline(filename, lineno, traceback.tb_frame.f_globals)
Run Code Online (Sandbox Code Playgroud)
无论如何,这是traceback模块用于将回溯转换为有用信息的内容.
由于字节码只有一个与之关联的行号,因此不能直接将字节码引回到源代码行的精确部分 ; 您必须自己解析该行以确定每个部分将发出的字节码然后将其与代码对象的字节码进行匹配.
您可以使用该ast模块执行此操作,但不能逐行执行此操作,因为您需要使用范围上下文来生成本地与单元格与全局名称查找的正确字节码.
这就是我最终解决问题的方法:我通过将原始程序中的每个函数调用包装在对辅助函数的调用中以及有关原始调用的源位置的信息来检测原始程序中的每个函数调用。实际上,我对控制程序中每个子表达式的求值感兴趣,因此我包装了每个子表达式。
e更准确地说:当我在原始程序中有一个表达式时,它变成了
_after(_before(location_info), e)
Run Code Online (Sandbox Code Playgroud)
在仪表化程序中。助手的定义如下:
def _before(location_info):
return location_info
def _after(location_info, value):
return value
Run Code Online (Sandbox Code Playgroud)
当跟踪器报告对 的调用时_before,我知道它将评估由 表示的位置处的表达式location_info(跟踪系统使我可以访问局部变量/参数,这就是我如何知道 的值location_info)。当跟踪器报告对 的调用时_after,我知道 所指示的表达式location_info刚刚被评估并且值位于 中value。
我可以将执行“事件处理”直接写入这些辅助函数中,并完全绕过跟踪系统,但我也出于其他原因需要它,所以我仅使用这些辅助函数来触发跟踪系统中的“调用”事件。
结果可以在这里看到: http: //thonny.org