您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

如何从subprocess.communicate()中捕获python中的流输出

如何从subprocess.communicate()中捕获python中的流输出

我可以想到一些解决方案。

#1:您可以直接进入源代码获取,复制和粘贴的代码communicate,并添加可打印每行内容代码以及对它们进行缓冲的代码。(如果您可能stdout由于死锁的父母而被自己阻止,则可以改用athreading.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其他异步框架中或使用它。(这使得它 能够 避免死锁问题,但它不保证 -你还是要确保服务管道正常。)

python 2022/1/1 18:36:46 有453人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶