我使用的是Python库,它对对象执行某些操作
do_something(my_object)
并改变它。在执行此操作时,它会将一些统计数据打印到stdout,我希望能够掌握这些信息。正确的解决方案是更改do_something()
以返回相关信息,
out = do_something(my_object)
但do_something()
的开发者还需要一段时间才能解决这个问题。作为一种变通方法,我考虑解析do_something()
写入标准输出的任何内容。
如何捕获代码中两点之间的标准输出,例如,
start_capturing()
do_something(my_object)
out = end_capturing()
发布于 2020-06-16 05:28:52
这是一个使用文件管道的异步解决方案。
import threading
import sys
import os
class Capturing():
def __init__(self):
self._stdout = None
self._stderr = None
self._r = None
self._w = None
self._thread = None
self._on_readline_cb = None
def _handler(self):
while not self._w.closed:
try:
while True:
line = self._r.readline()
if len(line) == 0: break
if self._on_readline_cb: self._on_readline_cb(line)
except:
break
def print(self, s, end=""):
print(s, file=self._stdout, end=end)
def on_readline(self, callback):
self._on_readline_cb = callback
def start(self):
self._stdout = sys.stdout
self._stderr = sys.stderr
r, w = os.pipe()
r, w = os.fdopen(r, 'r'), os.fdopen(w, 'w', 1)
self._r = r
self._w = w
sys.stdout = self._w
sys.stderr = self._w
self._thread = threading.Thread(target=self._handler)
self._thread.start()
def stop(self):
self._w.close()
if self._thread: self._thread.join()
self._r.close()
sys.stdout = self._stdout
sys.stderr = self._stderr
示例用法:
from Capturing import *
import time
capturing = Capturing()
def on_read(line):
# do something with the line
capturing.print("got line: "+line)
capturing.on_readline(on_read)
capturing.start()
print("hello 1")
time.sleep(1)
print("hello 2")
time.sleep(1)
print("hello 3")
capturing.stop()
发布于 2021-12-30 06:40:46
基于kindall
和ForeverWintr
的回答。
我为Python<3.4
创建了redirect_stdout
函数
import io
from contextlib import contextmanager
@contextmanager
def redirect_stdout(f):
try:
_stdout = sys.stdout
sys.stdout = f
yield
finally:
sys.stdout = _stdout
f = io.StringIO()
with redirect_stdout(f):
do_something()
out = f.getvalue()
https://stackoverflow.com/questions/16571150
复制相似问题