我有一个程序,取决于一个大的代码库,打印了许多不相关和恼人的消息。我想稍微清理它们,但由于它们的内容是动态生成的,我不能只为它们加油。
有没有办法在print语句上放置一个钩子? (我使用python 2.4,但我会对任何版本的结果感兴趣)。还有另一种方法可以找到输出来自哪个“打印”语句?
答案 0 :(得分:3)
严格地说,您所依赖的代码库(如库中)不应包含任何 print
语句。所以,你应该真的只删除所有。
除此之外,你可以猴子补丁stdout
:Adding a datetime stamp to Python print
答案 1 :(得分:3)
对于CPython2.5或更早版本:
import sys
import inspect
import collections
_stdout = sys.stdout
Record = collections.namedtuple(
'Record',
'frame filename line_number function_name lines index')
class MyStream(object):
def __init__(self, target):
self.target = target
def write(self, text):
if text.strip():
record = Record(*inspect.getouterframes(inspect.currentframe())[1])
self.target.write(
'{f} {n}: '.format(f = record.filename, n = record.line_number))
self.target.write(text)
sys.stdout = MyStream(sys.stdout)
def foo():
print('Hi')
foo()
产量
/home/unutbu/pybin/test.py 20: Hi
对于CPython2.6 +,我们可以使用
导入打印功能from __future__ import print_function
然后按照我们的意愿重定向:
from __future__ import print_function
import sys
import inspect
import collections
Record = collections.namedtuple(
'Record',
'frame filename line_number function_name lines index')
def myprint(text):
if text.strip():
record = Record(*inspect.getouterframes(inspect.currentframe())[1])
sys.stdout.write('{f} {n}: '.format(f = record.filename, n = record.line_number))
sys.stdout.write(text + '\n')
def foo():
print('Hi')
print = myprint
foo()
请注意inspect.currentframe
使用sys._getframe
,它不是所有Python实现的一部分。所以上面的解决方案可能仅适用于CPython。
答案 2 :(得分:2)
非常严重的黑客工作:
使用您喜欢的文本编辑器,使用您的搜索/查找功能。
找到所有的打印陈述。
并手动输入数字或标识符。 (或者如果你这样做就自动编写脚本)
执行此操作的脚本很简单,只需要使用正则表达式查找print
,然后将其替换为print ID,
,然后它们将全部相同,但您将获得数字。
欢呼声。
修改强>
除非有任何奇怪的格式,否则以下代码应该为您完成。
请注意,这只是您可以做到的一种方式的示例。不是真正的答案。
import re
class inc():
def __init__(self):
self.x = 0
def get(self):
self.x += 1
return self.x
def replacer(filename_in, filename_out):
i = inc()
out = open(filename_out, 'w')
with open(filename_in) as f:
for line in f:
out.write("%s\n" % re.sub(r'print', 'print %d,' % i.get(), line))
我使用了一个基本的增量器类,以防你想拥有某种更复杂的ID,而不是只有一个计数器。
答案 3 :(得分:1)
以下是Jeeeyul came up with for Java的一个技巧:将输出流(即sys.out
)替换为写入换行符时注意到的内容。
如果此标志为true,则在写入下一个字节时抛出异常。在同一个地方捕获异常,沿堆栈跟踪向上走,直到找到不属于“调试流编写器”的代码。
伪代码:
class DebugPrintln:
def __init__(self):
self.wasLF = False
def write(self, x):
if self.wasLF:
self.wasLF = False
frames = traceback.extract_stack()
... find calling code and output it ...
if x == '\n':
self.wasLF = true
super.write(x)
答案 4 :(得分:1)
在恶劣的环境中(在一些奇怪的二进制库中完成输出)你也可以使用strace -e write
(以及更多选项)。如果你没有读取strace的输出,那么straced程序会等到你执行,所以你可以发送一个信号,看看它死了。