从 python 中的多个线程捕获打印输出
Capture print output from multiple threads in python
我有一个函数可以在内部并行启动多个线程 运行。线程打印一些东西,我想从外部函数捕获这个输出。我尝试了下一个代码来捕获输出:
import sys, io
stdout = sys.stdout
sys.stdout = io.StringIO()
threads_conn(connect, devices) #- here many threads starts with many print inside
output = sys.stdout.getvalue()
sys.stdout = stdout
print(output)
此代码有效。但问题是只有当所有的广告都完成时才会打印输出。所以我冻结了。一旦所有线程都完成 - 打印整个输出。我想要的 - 一旦在内部生成就可以输出 - 换句话说是实时的。现在我立即打印了整个输出缓冲区。
如何让所有线程实时输出?
你想做的是写你自己的TextIOBase
class(或者,如果你想要二进制数据,你自己写RawIOBase
然后包装一只股票TextIOWrapper
周围),您可以在其中放置您想要的任何行为。
从the docs可以看出。您需要为 TextIOBase
实施的是 detach
、read
、readline
和 write
。前三个与您正在做的事情无关。
那么,您的 write
应该是什么样的?嗯,这取决于你想做什么。
听起来您的目标是将所有内容都发送到真正的标准输出和 StringIO
。如果是这样,这是非常微不足道的。
唯一的问题是,如果其中一个目标引发异常,或者写入的字节数少于另一个,等等,你想做什么。由于 IOString
永远不会做任何一个,我们可以写一些非常愚蠢的东西,只是假设真正的标准输出所做的一切都是正确的。
class TeeTextIO(io.TextIOBase):
def __init__(self, target):
self.target = target
self.stringio = io.StringIO()
def write(self, s):
writecount = self.target.write(s)
self.stringio.write(s[:writecount])
return writecount
现在:
stdout = sys.stdout
sys.stdout = TeeTextIO(sys.stdout)
threads_conn(connect, devices) #- here many threads starts with many print inside
output = sys.stdout.stringio.getvalue()
sys.stdout = stdout
现在,输出已经进入真正的 stdout
,但它也被存储在 StringIO
中,供您以后使用。
(请注意,此 class 将适用于 any TextIOBase
,就像您 open
的文件一样,而不仅仅是 stdout
。我们没有花任何钱让它通用,所以为什么不呢?)
如果您想做一些完全不同的事情怎么办,比如将每个 write
随机分布在 10 个不同的文件中?应该很明显:
class SpreadTextWriter(io.TextIOBase):
def __init__(self, *files):
self.files = files
def write(self, s):
return random.choice(self.files).write(s)
我有一个函数可以在内部并行启动多个线程 运行。线程打印一些东西,我想从外部函数捕获这个输出。我尝试了下一个代码来捕获输出:
import sys, io
stdout = sys.stdout
sys.stdout = io.StringIO()
threads_conn(connect, devices) #- here many threads starts with many print inside
output = sys.stdout.getvalue()
sys.stdout = stdout
print(output)
此代码有效。但问题是只有当所有的广告都完成时才会打印输出。所以我冻结了。一旦所有线程都完成 - 打印整个输出。我想要的 - 一旦在内部生成就可以输出 - 换句话说是实时的。现在我立即打印了整个输出缓冲区。 如何让所有线程实时输出?
你想做的是写你自己的TextIOBase
class(或者,如果你想要二进制数据,你自己写RawIOBase
然后包装一只股票TextIOWrapper
周围),您可以在其中放置您想要的任何行为。
从the docs可以看出。您需要为 TextIOBase
实施的是 detach
、read
、readline
和 write
。前三个与您正在做的事情无关。
那么,您的 write
应该是什么样的?嗯,这取决于你想做什么。
听起来您的目标是将所有内容都发送到真正的标准输出和 StringIO
。如果是这样,这是非常微不足道的。
唯一的问题是,如果其中一个目标引发异常,或者写入的字节数少于另一个,等等,你想做什么。由于 IOString
永远不会做任何一个,我们可以写一些非常愚蠢的东西,只是假设真正的标准输出所做的一切都是正确的。
class TeeTextIO(io.TextIOBase):
def __init__(self, target):
self.target = target
self.stringio = io.StringIO()
def write(self, s):
writecount = self.target.write(s)
self.stringio.write(s[:writecount])
return writecount
现在:
stdout = sys.stdout
sys.stdout = TeeTextIO(sys.stdout)
threads_conn(connect, devices) #- here many threads starts with many print inside
output = sys.stdout.stringio.getvalue()
sys.stdout = stdout
现在,输出已经进入真正的 stdout
,但它也被存储在 StringIO
中,供您以后使用。
(请注意,此 class 将适用于 any TextIOBase
,就像您 open
的文件一样,而不仅仅是 stdout
。我们没有花任何钱让它通用,所以为什么不呢?)
如果您想做一些完全不同的事情怎么办,比如将每个 write
随机分布在 10 个不同的文件中?应该很明显:
class SpreadTextWriter(io.TextIOBase):
def __init__(self, *files):
self.files = files
def write(self, s):
return random.choice(self.files).write(s)