我试图将一些数据提供给连接的一系列进程 通过管道。但是,我无法将其关闭。
p1 = subprocess.Popen("sort", stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p2 = subprocess.Popen("uniq", stdin=p1.stdout, stdout=subprocess.PIPE)
p1.communicate(r"""
a
b
c
a""")
out, _ = p2.communicate()
print(out)
现在该程序正在等待。是否有另一种方式我应该通知p1
输入结束?
- 注意:我在Windows上运行
答案 0 :(得分:2)
您需要在第一个程序上关闭stdin。
需要注意的一些事项:
管道之间有缓冲区(subprocess.PIPE为您创建的),每个平台和用途的大小各不相同。不要担心这一点,因为它不像以下那样重要:
在这种情况下,sort
要求在能够排序之前读取完整的输入(如果您不知道它们是什么,则无法对事物进行排序)。
由于2
,它有自己的缓冲区来收集并等待文件描述符被关闭,表示它已完成;)
编辑:这是我正在制作的例子。我发现直接使用管道更加个性化,因为您可以在生成流程之前单独构建输入:
In [2]: import os
...: import subprocess
...:
...: # A raw os level pipe, which consists of two file destriptors
...: # connected to each other, ala a "pipe".
...: # (This is what subprocess.PIPE sets up btw, hence it's name! ;)
...: read, write = os.pipe()
...:
...: # Write what you want to it. In python 2, remove the `b` since all `str`ings are `byte` strings there.
...: os.write(write, b"blahblahblah")
...:
...: # Close stdin to signal completion of input
...: os.close(write)
...:
...: # Spawn process using the pipe as stdin
...: p = subprocess.Popen(['cat'], stdin=read)
...:
blahblahblah
另外,请确保p.wait()
完成此过程,否则您最终可能会遇到尚未获得完整结果的情况。
答案 1 :(得分:1)
免责声明:此处不是专家。我之前没有使用communicate()
,但是......
首先,在阅读docs for communicate
时,它意味着从正在运行的进程的stdout / stderr中读取数据:
从stdout和stderr读取数据
所以我想你的python程序会读取p1
执行sort
的输出。或者确切地说,在我的Linux机器上,行为似乎不是确定性的 - 有时它是Python代码,有时它是p2/uniq
读取p1/sort
的标准输出。我猜他们只是在争夺数据。
看起来communicate()
的东西是某种组合,对你的用例(p1/sort
)来说有点太多了。这对p2/uniq
很好。
另一方面,如果你尝试过:
import subprocess
p1 = subprocess.Popen("sort", stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p2 = subprocess.Popen("uniq", stdin=p1.stdout, stdout=subprocess.PIPE)
p1.stdin.write(r"""
a
b
c
a""")
p1.stdin.close()
out, _ = p2.communicate()
print(out)
它似乎有效。