有时我会在项目中留下调试打印语句,很难找到它。有什么方法可以找出特别印刷什么线?
旁注
智能搜索似乎可以解决大多数情况。在Pydev(和其他IDE)中有一个Search函数,它允许搜索项目中的所有文件。当然,使用带有-rn标志的grep可以获得类似的效果,尽管您只获得行号而不是直接链接。
“print(”在我的代码中工作得更好,并且通常在print语句中有额外的文本可以使用正则表达式进行搜索。最困难的情况是当你刚刚编写print(x)时,尽管这样可以搜索正则表达式,其中x内的值不以引号开头或结尾(谢谢!BecomingGuro)
答案 0 :(得分:33)
你问过静态解决方案。这是一个动态的。假设您运行代码并查看错误的打印或写入sys.stdout,并想知道它来自何处。您可以替换sys.stdout并让异常回溯帮助您:
>>> import sys
>>> def go():
... sys.stdout = None
... print "Hello!"
...
>>> go()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in go
AttributeError: 'NoneType' object has no attribute 'write'
>>> print "Here"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'write'
>>>
对于更复杂的东西,将'sys.stdout'替换为报告print语句所在位置的东西。我将使用traceback.print_stack()来显示完整的堆栈,但您可以执行其他操作,例如使用sys._getframe()查找一个堆栈级别以获取行号和文件名。
import sys
import traceback
class TracePrints(object):
def __init__(self):
self.stdout = sys.stdout
def write(self, s):
self.stdout.write("Writing %r\n" % s)
traceback.print_stack(file=self.stdout)
sys.stdout = TracePrints()
def a():
print "I am here"
def b():
a()
b()
这是输出
Writing 'I am here'
File "stdout.py", line 19, in <module>
b()
File "stdout.py", line 17, in b
a()
File "stdout.py", line 14, in a
print "I am here"
File "stdout.py", line 9, in write
traceback.print_stack(file=self.stdout)
Writing '\n'
File "stdout.py", line 19, in <module>
b()
File "stdout.py", line 17, in b
a()
File "stdout.py", line 14, in a
print "I am here"
File "stdout.py", line 9, in write
traceback.print_stack(file=self.stdout)
如果你走这条路线,也可以看一下'linecache'模块,你可以用它来打印这行的内容。请查看traceback.print_stack的实现,了解如何执行此操作。
答案 1 :(得分:5)
This article可以证明这样做非常有价值。查找line
事件并从框架中提取方法名称(如果我没记错的话)。可以找到更多信息here
答案 2 :(得分:4)
使用grep:
grep -rn print .
答案 3 :(得分:2)
最简单的方法是使用“debug_print”函数而不是普通的“print”。
这样你就可以重新定义这个功能,并确保你没有错过一个...... 如果您需要再次调试该代码而不是每次来回编辑代码,仍然可以使用它们。
(是的,离开debug_print调用可以吃掉一些性能:只在这种情况下删除它们)
在您的修订控制系统中编写任何代码之前,在代码中发现“仅调试”语句是进行 diff 的一个非常好的理由! (知道在提交注释中放入什么是第二个很好的理由!)
答案 4 :(得分:2)
请改用printf函数。以下内容来自Infrequently Answered Python Questions
def printf(format, *args):
"""Format args with the first argument as format string, and print.
If the format is not a string, it is converted to one with str.
You must use printf('%s', x) instead of printf(x) if x might
contain % or backslash characters."""
print str(format) % args,
现在,当您从调试转到生产时,您将重新定义printf,如下所示:
def printf(format, *args):
pass
这样做的好处是,如果您必须返回并维护代码以添加功能或修复错误,则可以重新打开printf。
答案 5 :(得分:1)
使用grep与巧妙构造的正则表达式(不以引号开头或结尾)似乎是你最好的选择。
答案 6 :(得分:0)
这可能不直接回答你的问题,但是如果你以有效调试和编写代码的方式使用pdb(python调试器),你就可以逃脱大量的print语句。
我知道它有效,因为99%的时间你不想打印东西,但你想在某个地方设置一个断点,看看变量是什么以及程序到达了多远。
HTH
答案 7 :(得分:0)
我通常在我的代码中执行此操作:
(靠近顶部):
debug=True
(稍后)
如果是debug:print“这是一个调试语句.x =”,x
然后,当我想取出所有的调试语句时,我将调试更改为:
调试=假
答案 8 :(得分:0)
对于Python3,我使用它打补丁后打印出文件名,行号和功能
import builtins
from inspect import getframeinfo, stack
original_print = print
def print_wrap(*args, **kwargs):
caller = getframeinfo(stack()[1][0])
original_print("FN:",caller.filename,"Line:", caller.lineno,"Func:", caller.function,":::", *args, **kwargs)
builtins.print = print_wrap