gpt4 book ai didi

python - 使用 subprocess.Popen 时将大量数据通过管道传输到标准输入

转载 作者:太空狗 更新时间:2023-10-29 17:15:55 25 4
gpt4 key购买 nike

我有点难以理解解决这个简单问题的 python 方法是什么。

我的问题很简单。如果您使用以下代码,它将挂起。这在子流程模块文档中有详细记录。

import subprocess

proc = subprocess.Popen(['cat','-'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
)
for i in range(100000):
proc.stdin.write('%d\n' % i)
output = proc.communicate()[0]
print output

搜索解决方案(有一个非常有见地的线程,但我现在已经丢失了)我找到了这个使用显式 fork 的解决方案(以及其他解决方案):

import os
import sys
from subprocess import Popen, PIPE

def produce(to_sed):
for i in range(100000):
to_sed.write("%d\n" % i)
to_sed.flush()
#this would happen implicitly, anyway, but is here for the example
to_sed.close()

def consume(from_sed):
while 1:
res = from_sed.readline()
if not res:
sys.exit(0)
#sys.exit(proc.poll())
print 'received: ', [res]

def main():
proc = Popen(['cat','-'],stdin=PIPE,stdout=PIPE)
to_sed = proc.stdin
from_sed = proc.stdout

pid = os.fork()
if pid == 0 :
from_sed.close()
produce(to_sed)
return
else :
to_sed.close()
consume(from_sed)

if __name__ == '__main__':
main()

虽然这个解决方案在概念上非常容易理解,但它使用了一个多进程并且与子进程模块相比卡在了太低的级别(那里只是为了隐藏这种东西......)。

我想知道:是否有一个使用不会挂起的子进程模块的简单而干净的解决方案,或者要实现这种模式,我必须退后一步并实现一个旧式选择循环或一个显式 fork ?

谢谢

最佳答案

如果您想要一个纯 Python 解决方案,则需要将读取器或写入器放在单独的线程中。 threading 包是执行此操作的轻量级方法,可以方便地访问公共(public)对象并且没有困惑的 fork 。

import subprocess
import threading
import sys

proc = subprocess.Popen(['cat','-'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
)
def writer():
for i in range(100000):
proc.stdin.write(b'%d\n' % i)
proc.stdin.close()
thread = threading.Thread(target=writer)
thread.start()
for line in proc.stdout:
sys.stdout.write(line.decode())
thread.join()
proc.wait()

看到 subprocess 模块现代化以支持流和协程可能会很好,这将允许更优雅地构建混合 Python 片段和 shell 片段的管道。

关于python - 使用 subprocess.Popen 时将大量数据通过管道传输到标准输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5911362/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com