我可以想到一些解决方案。
#1:您可以直接进入源代码以获取,复制和粘贴的代码
communicate,并添加可打印每行内容的代码以及对它们进行缓冲的代码。(如果您可能
stdout由于死锁的父母而被自己阻止,则可以改用a
threading.Queue或其他东西。)这显然有点麻烦,但这很简单,而且很安全。
但实际上,这
communicate很复杂,因为它需要完全通用,并处理您不需要的情况。您需要的只是中心技巧:在问题上抛出线程。
read您只需要一个专用的读取器线程,它不会使任何操作变慢或在调用之间阻塞。
像这样:
self.process = subprocess.Popen(self.cmd, stdout=subprocess.PIPE)lines = []def reader(): for line in self.process.stdout: lines.append(line) sys.stdout.write(line)t = threading.Thread(target=reader)t.start()self.process.wait()t.join()
您可能需要在
reader线程中进行一些错误处理。我不确定100%是否可以
readline在这里安全使用。但这要么有效,要么接近。
#2:或者您可以创建一个包装器类,该包装器类接受一个文件对象,并在每次有人访问它时发球到
stdout/
。然后,手动创建管道,并传递包裹的管道,而不是使用automagic
。这个问题与#1完全相同(意味着没有问题,或者您需要使用a或其他内容(如果可以阻止))。
stderr``read``PIPE``Queue``sys.stdout.write
像这样:
class TeeReader(object): def __init__(self, input_file, tee_file): self.input_file = input_file self.tee_file = tee_file def read(self, size=-1): ret = self.input_file.read(size) if ret: self.tee_file.write(ret) return ret
换句话说,它包装了一个文件对象(或类似对象的东西),并像一个文件对象一样工作。(当使用时
PIPE,它
process.stdout是Unix上的真实文件对象,但可能只是在Windows上具有类似的行为。)您需要委派的任何其他方法
input_file都可以直接委派,而无需进行任何额外包装。要么试试这个,看看有什么方法
communicate得到
AttributeException,正在寻找和代码的那些明确,或者做一般的
__getattr__伎俩委托的一切。PS,如果您担心这种“文件对象”的想法,即磁盘存储,请阅读Wikipedia上的Everything是一个文件。
#3:最后,您可以获取PyPI上的“异步子进程”模块之一,或将其包含在
twisted其他异步框架中或使用它。(这使得它 能够 避免死锁问题,但它不
保证 -你还是要确保服务管道正常。)



