Python子进程:如何三次使用管道? [复制]

分享于2023年03月08日 pipe python subprocess 问答
【问题标题】:Python subprocess: how to use pipes thrice? [duplicate]Python子进程:如何三次使用管道? [复制]
【发布时间】:2012-03-28 04:33:17
【问题描述】:

我想在下面一行使用子进程:

convert ../loxie-orig.png bmp:- | mkbitmap -f 2 -s 2 -t 0.48 | potrace -t 5 --progress -s -o ../DSC00232.svg

感谢其他帖子 the subprocess documentation 但在示例中我们只使用了两次管道。

所以,我尝试了三个命令中的两个,它可以工作

p1 = subprocess.Popen(['convert', fileIn, 'bmp:-'], stdout=subprocess.PIPE)
# p2 = subprocess.Popen(['mkbitmap', '-f', '2', '-s', '2', '-t', '0.48'], stdout=subprocess.PIPE)
p3 = subprocess.Popen(['potrace', '-t' , '5', '-s' , '-o', fileOut], stdin=p1.stdout,stdout=subprocess.PIPE)
p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p3 exits.
output = p3.communicate()[0]

你能帮我完成第三个命令吗?

非常感谢。

  • 您是否再次尝试使用相同进程的第三个命令?
  • 为什么您尝试过的方法不起作用?管道在 shell 中所做的所有事情就是将一个进程的标准输出连接到另一个进程的标准输入。
  • 我不知道我必须在哪里关闭 p2 以及如何对输出进行编码......
  • @Zorkzyd 从示例中可以清楚地看出进程如何相互挂钩, P1.STDOUT -> P2.STDIN : P2.STDOUT -> P3.STDIN : P3 具有您想要的输出。您可能只需要仔细阅读
  • 对不起,我是新手。我试图自己理解,但这并不总是那么容易……但是,非常感谢您的回答。

【解决方案1】:

只需在相同的示例之后添加第三个命令:

p1 = subprocess.Popen(['convert', fileIn, 'bmp:-'], stdout=subprocess.PIPE)
p2 = subprocess.Popen(['mkbitmap', '-f', '2', '-s', '2', '-t', '0.48'], 
     stdin=p1.stdout, stdout=subprocess.PIPE)
p1.stdout.close()
p3 = subprocess.Popen(['potrace', '-t' , '5', '-s' , '-o', fileOut],        
     stdin=p2.stdout,stdout=subprocess.PIPE)
p2.stdout.close()

output = p3.communicate()[0]

【讨论】:

  • 我不这么认为,既然它们都是链接的,我认为应该只需要一个 communicate 调用。成功了吗?
  • 是的,现在可以使用了。谢谢你:)
  • p1.stdout.close() p2.stdout.close() 跟在 output = p3.communicate()[0] 之后有关系吗?
  • 你为什么不用 p1.wait() ,就在 p1.stdout.close() p2.wait() 之前,就在 p2.stdout.close() 之前;这个答案( stackoverflow.com/a/13332300/2402577 )使用了哪个( ps.wait() )? @HunterMcMillen
  • 值得注意的是,stdin 必须是有效的 IO 对象。尝试使用 urllib3(通过请求)没有运气 - 存在死锁。在我看来,通常子流程在不必要的低级别运行。我正在使用请求,但必须通过子进程更改“curl”以使其工作而不会出现死锁。