我想处理第三方脚本的实时输出,打印一些匹配模式的行,但跳过其他行:
coordinates
我使用def thirdparty_code():
from random import choice
stuff = ['keep: important stuff', 'ignore: boring stuff']
while True:
chosen_line = choice(stuff)
print(chosen_line)
(将线传递到虚拟IO)和扩展的redirect_stdout
(用作IO,但也调用过滤功能)。但是,当我在处理函数中调用StringIO
时,会得到print()
-这并不意外:
RecursionError
我想知道是否有可能摆脱重定向,例如在from io import StringIO
from contextlib import redirect_stdout
class StringIOWithCallback(StringIO):
def __init__(self, callback, **kwargs):
super().__init__(**kwargs)
self.callback = callback
def write(self, s):
super().write(s)
self.callback(s)
def filter_boring_stuff_out(line):
if line.startswith('ignore'):
return
print(line)
my_io = StringIOWithCallback(filter_boring_stuff_out)
with redirect_stdout(my_io):
thirdparty_code()
函数中指定file
参数,以便将其打印到实际的标准输出。我知道我可以轻松使用标准错误流:
print()
但是我特别想使用标准输出。有一种不错的,Python方式的方法吗?
答案 0 :(得分:3)
重定向stdout
后,您可以通过__stdout__
轻松地将其重置,因为它可以保存原始值。
sys.stdout = redirected_stdout
...
...
sys.stdout = sys.__stdout__
如果您不断发现自己在切换这些输出流,则应该创建一个函数以输出到重定向的流:
def redirect(*args):
print(*args, file=redirected_file)
redirect(...) # redirect this output
print(...) # use standard stream
答案 1 :(得分:1)
一旦我写了我的问题,我已经意识到在调用重定向之前,只需要将标准输出对象import sys
print(line, file=sys.stderr)
保存到一个变量中即可。
sys.stdout
但一如既往-我很乐意了解其他可能的解决方案。
答案 2 :(得分:1)
您可以重定向stdout
并忽略所有以ignore
开头的消息。如果您这样做,所有print
都将被拦截。如果您尝试从您无权访问或不想更改的代码中过滤消息,则此方法会更好。
import sys
from contextlib import redirect_stdout
class Filter_Out:
def __init__(self, *_, start=None, anywhere=None, end=None):
self.last_ignore = False
self.start = start
self.anywhere = anywhere
self.end = end
self.terminal = sys.stdout
def write(self, txt):
if (self.start and txt.startswith(self.start)) or \
(self.end and txt.endswith(self.end)) or \
(self.anywhere and self.anywhere in txt):
self.last_ignore = True
return
if self.last_ignore and txt == '\n':
self.last_ignore = False
else:
self.terminal.write(txt)
def flush(self):
pass
with redirect_stdout(Filter_Out(start='ignore', anywhere='4')):
print("test")
print("test2")
print("ignore: test2") # will not print because it started with ignore
print("test1")
print("test42") # will not print because it had 4 in it