Python程序的跟踪表

Chr*_*ord 7 python

有没有办法获取Python程序的跟踪表?或者一个程序运行另一个程序并获取其跟踪表?我是一名老师,试图完美地验证我们在测试中使用的跟踪问题的答案.

因此,例如,假设我有一个名为problem1.py以下内容的Python程序:

problem1.py

 a = 1
 b = 2

 a = a + b
Run Code Online (Sandbox Code Playgroud)

执行推定的程序traceTable.py应该如下:

 $ python traceTable.py problem1.py
 L || a | b
 1 || 1 |
 2 || 1 | 2
 4 || 3 | 2
Run Code Online (Sandbox Code Playgroud)

(或者使用不同语法的相同信息)

我查看了trace模块,我看不到它支持这个方法.


更新

女士们,先生们:使用Ned Batchelder的优秀建议,我给你们traceTable.py!

好吧......差不多.正如您在Ned Batchelder的示例中所看到的,frame.f_lineno并不总是直观地表现(例如,第3行和第4行都被计为第4行),但行号足够接近以获得相当好的参考.此外,所有计算都是正确的.

我用一个包含if语句的长程序对它进行了测试,并给出了正确的表(没有行号).

您还会注意到,由于在他提到的大型程序中考虑了"更有趣的数据生态系统",我的程序比Ned Batchelder的概念验证要长得多.在使用范围execfile和管理它所需的所有变量以及降低噪声(ala ignored_variables)以及产生正确的字符串输出时,需要更多的代码:

traceTable.py

 '''
 Usage: python traceTable.py program

     -program  Python program to be traced
 '''

 import sys

 if len(sys.argv) < 2:
      print __doc__
      exit()
 else:
      file_name = sys.argv[1]

 past_locals = {}
 variable_list = []
 table_content = ""

 ignored_variables = set([
      'file_name',
      'trace',
      'sys',
      'past_locals',
      'variable_list',
      'table_content',
      'getattr',
      'name',
      'self',
      'object',
      'consumed',
      'data',
      'ignored_variables'])

 def trace(frame, event, arg_unused):
      global past_locals, variable_list, table_content, ignored_variables
      relevant_locals = {}
      all_locals = frame.f_locals.copy()
      for k,v in all_locals.items():
           if not k.startswith("__") and k not in ignored_variables:
                relevant_locals[k] = v
      if len(relevant_locals) > 0 and past_locals != relevant_locals:
           for i in relevant_locals:
                if i not in past_locals:
                     variable_list.append(i)
           table_content += str(frame.f_lineno) + " || "
           for variable in variable_list:
                table_content += str(relevant_locals[variable]) + " | "
           table_content = table_content[:-2]
           table_content += '\n'
           past_locals = relevant_locals
      return trace

 sys.settrace(trace)

 execfile(file_name)

 table_header = "L || "
 for variable in variable_list:
      table_header += variable + ' | '
 table_header = table_header[:-2]
 print table_header
 print table_content
Run Code Online (Sandbox Code Playgroud)

调用时,它会产生输出

 $ python traceTable.py problem1.py
 L || a | b
 2 || 1
 4 || 1 | 2
 4 || 3 | 2
Run Code Online (Sandbox Code Playgroud)

Ned*_*der 10

这不是当前Python跟踪工具支持的用例,但应该可以构建.我不知道你如何决定输出哪些列.在您的示例中,a和b是唯一的局部变量,但较大的程序会有更有趣的数据生态系统.

更新:这是一个简单的概念证明:

 1     import sys
 2
 3     def trace(frame, event, arg_unused):
 4         print event, frame.f_lineno, frame.f_locals
 5         return trace
 6
 7     sys.settrace(trace)
 8
 9     def foo():
10         a = 1
11         b = 2
12
13         a = a + b
14
15     foo()
Run Code Online (Sandbox Code Playgroud)

运行时,输出为:

call 9 {}
line 10 {}
line 11 {'a': 1}
line 13 {'a': 1, 'b': 2}
return 13 {'a': 3, 'b': 2}
Run Code Online (Sandbox Code Playgroud)