【发布时间】:2013-12-20 12:34:35
【问题描述】:
我有一个复杂的 python 项目,其中包含许多模块、记录器、扭曲的延迟和其他东西。
在代码中的某处,某行被打印到日志中,我想找出在哪里。通常我只是在代码库中搜索该字符串,但现在该字符串是动态生成的,因此不可搜索。
如果有什么方法可以在某种调试模式下运行 python,我会徘徊,并告诉它在 sdout 中出现某些模式时停止,然后在停止的代码中打印位置?
【问题讨论】:
我有一个复杂的 python 项目,其中包含许多模块、记录器、扭曲的延迟和其他东西。
在代码中的某处,某行被打印到日志中,我想找出在哪里。通常我只是在代码库中搜索该字符串,但现在该字符串是动态生成的,因此不可搜索。
如果有什么方法可以在某种调试模式下运行 python,我会徘徊,并告诉它在 sdout 中出现某些模式时停止,然后在停止的代码中打印位置?
【问题讨论】:
替换sys.stdout怎么样?
例如:
import sys
import traceback
class StacktraceOnPrint:
def __init__(self, orig_stdout, substring):
self.orig_stdout = orig_stdout
self.substring = substring
def write(self, txt):
if self.substring in txt:
traceback.print_stack() # OR import pdb; pdb.set_trace()
self.orig_stdout.write(txt)
sys.stdout = StacktraceOnPrint(sys.stdout, 'blah')
print 'test ...'
print 'Hello blah.'
print 'test ...'
注意 traceback.print_stack 使用 sys.stderr。如果您想捕捉sys.stderr,请使用不同的功能(如traceback.format_stack)。否则它会永远递归;导致RuntimeError: maximum recursion depth exceeded ..
【讨论】:
您可以使用pdb module。 这将使您能够在运行时以交互方式调试代码。 您可能可以编写一个脚本来“逐步”运行您的程序,直到您在日志文件中读取该行。
【讨论】:
您可以通过设置格式化程序为每个日志记录包含路径名、模块、funcName、行号
formatter = logging.Formatter('[%(asctime)s] p%(process)s {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s','%m-%d %H:%M:%S')
【讨论】:
看起来你正在使用扭曲。您可以在pdb 下启动您的扭曲程序。检查twistd --help:
...
-b, --debug run the application in the Python Debugger (implies
nodaemon), sending SIGUSR2 will drop into debugger
...
在pdb 下启动程序后,你可以在你喜欢的地方设置断点。您还可以指定要执行断点的条件:
(Pdb) b myfunc, somecondition
但在您的特定情况下,似乎很难检测到破坏程序的地方。
所以你可以考虑另一种方法。例如,您可以将日志重定向到某些脚本的标准输入。此脚本监视特定的日志行。当它检测到有问题的行时,脚本会将SIGUSR2 发送到扭曲的程序,然后它会进入调试器。之后,只需使用 pdb 检查您的程序。
【讨论】: