subprocess.Popen管道如何在Python中工作?
我完全意识到相关问题的存在,但他们都非常模糊,并且未能清楚地解释每一步的进展。 所提供的例子通常没有经过测试,并且没有提供关于如何使它们适应不同场景的信息。 以下是问题以及Python的文档:
这基本上是我想要实现的,但在Python中:
curl http://asdf.com/89asdf.gif | convert -resize 80x80 - - | icat -k -
下面是我花了几个小时将以上答案的部分和部分进行了总结:
import requests
import subprocess
from subprocess import Popen, PIPE, STDOUT
url = 'http://asdf.com/89asdf.gif'
img = requests.get(url)
p1 = subprocess.Popen(['convert', '-resize', '80x80', '-', '-'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p2 = subprocess.Popen(['icat', '-k', '-'], stdin=p1.stdout, stdout=subprocess.PIPE)
p1.communicate(img.content)
print p2.stdout
这是我的代码,这次根据你的回答进行了改进:
import requests
from subprocess import Popen, PIPE, STDOUT
url = 'http://asdf.com/89asdf.gif'
img = requests.get(url)
p1 = Popen(['convert', '-resize', '80x80', '-', '-'], stdin=PIPE, stdout=PIPE)
p2 = Popen(['icat', '-k', '-'], stdin=p1.stdout, stdout=PIPE)
p1.stdin.write(img.content)
p1.stdin.close()
p1.stdout.close()
output = p2.communicate()[0]
print output
注意: icat
输出256色端子的图像。 我已经设法在另一个问题上成功地打印输出。 在icat
处理过的终端中,典型的图像看起来像这样:
请纠正我错在哪里,但这是我目前的理解:
p1.communicate(img.content)
:设置p1
的STDIN。 p1
的STDIN是subprocess.PIPE
,这是什么p1.communicate(mg.content)
提供。 p2
的STDIN是p1
的STDOUT,它是通过convert
调整大小的图像。 print
出p2
的STDOUT,这应该是icat
提供的ASCII颜色的图像。 问题:
stdin=subprocess.PIPE
和stdin=PIPE
。 有什么不同? 有人能解释过程中究竟发生了什么,以及我的代码出了什么问题? 这整个管道业务必须比看起来简单,我很想知道它是如何工作的。
Q1。 无论是subprocess.PIPE
还是PIPE
,它们都引用相同的符号,这是来自subprocess
模块的PIPE
。 以下内容完全相同:
# Version 1
import subprocess
proc = subprocess.Popen(['ls'], stdout=subprocess.PIPE)
output = proc.communicate()[0]
# Version 2
from subprocess import PIPE, Popen
proc = Popen(['ls'], stdout=PIPE)
output = proc.communicate()[0]
Q2。 communicate()
实际上是在将输入发送到p1的STDIN流中。 尽管在调用Popen
构造函数时子进程确实存在并且正在运行,但在您的特定情况下, convert
实用程序似乎在实际通过STDIN接收内容之前不会执行任何操作。 如果它是一个交互性较低的命令(例如ls
),那么它不会等到communicate()
做任何事情。
更新的内容在你的情况下,而不是使用communicate
发送输入到P1,而是尝试以下内容:
p1.stdin.write(img.content)
p1.stdin.close()
p1.stdout.close() # Protect against the busted pipe condition when p2 finishes before p1
output = p2.communicate()[0]
print output
看看你有没有更好的运气。
Q1。 没有区别,他们都是subprocess.PIPE
....
Q2。 你不必这样做,你可以轻松做到这一点
p1.stdin.write(img.content)
(事实上,那正是通信的那部分......)
communicate
被使用,因为它阻塞直到进程结束(在这种情况下,所以它的标准输出可以提供给p2.stdin(也许?)), write
只需写入管道并继续到文件中的下一行python