在Python中查找print语句

时间:2009-10-24 09:36:07

标签: python

有时我会在项目中留下调试打印语句,很难找到它。有什么方法可以找出特别印刷什么线?

旁注

智能搜索似乎可以解决大多数情况。在Pydev(和其他IDE)中有一个Search函数,它允许搜索项目中的所有文件。当然,使用带有-rn标志的grep可以获得类似的效果,尽管您只获得行号而不是直接链接。

“print(”在我的代码中工作得更好,并且通常在print语句中有额外的文本可以使用正则表达式进行搜索。最困难的情况是当你刚刚编写print(x)时,尽管这样可以搜索正则表达式,其中x内的值不以引号开头或结尾(谢谢!BecomingGuro)

9 个答案:

答案 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