如何使用subprocess.Popen通过管道连接多个进程?
如何使用Python subprocess
模块执行以下shell命令?
echo "input data" | awk -f script.awk | sort > outfile.txt
输入数据将来自一个字符串,所以我实际上并不需要echo
。 我有这么远,任何人都可以解释我如何通过sort
这个问题吗?
p_awk = subprocess.Popen(["awk","-f","script.awk"],
stdin=subprocess.PIPE,
stdout=file("outfile.txt", "w"))
p_awk.communicate( "input data" )
更新 :请注意,虽然下面接受的答案实际上并没有回答问题的问题,但我相信S.Lott是正确的,最好避免必须首先解决这个问题!
你会对以下事情感到高兴。
import subprocess
awk_sort = subprocess.Popen( "awk -f script.awk | sort > outfile.txt",
stdin=subprocess.PIPE, shell=True )
awk_sort.communicate( b"input datan" )
将部分工作委托给shell。 让它用流水线连接两个进程。
如果将'script.awk'重写为Python,你会感到很开心,从而消除awk和管道。
编辑 。 提出awk没有帮助的一些原因。
[通过评论回复的原因太多了。]
Awk正在增加一个没有重要价值的步骤。 关于awk的处理没有什么独特的,Python不处理。
对awk进行流水线排序以处理大量数据可能会缩短处理时间。 对于短的数据集,它没有显着的好处。 快速测量awk >file ; sort file
awk >file ; sort file
和awk | sort
awk | sort
会揭示并发的帮助。 排序,它很少帮助,因为排序不是一次性过滤器。
“Python排序”处理的简单性(而不是“Python来排序”)可以防止在这里提出的确切类型的问题。
Python - 虽然比awk更热门 - 但它也是明确的,其中awk具有对新手不透明的某些隐含规则,并且会让非专业人员感到困惑。
awk(如shell脚本本身)增加了另一种编程语言。 如果所有这些都可以用一种语言来完成(Python),那么消除shell和awk编程就可以消除两种编程语言,从而使人们可以专注于任务的产生价值的部分。
底线:awk无法增加显着的价值。 在这种情况下,awk是一个净成本; 它增加了足够的复杂性,有必要提出这个问题。 删除awk将是一个净收益。
边栏为什么建立管道( a | b
)太难了。
当shell遇到a | b
a | b
必须做到以下几点。
分叉原壳的子过程。 这最终会变成b。
建立一个os管道。 (不是Python子os.pipe()
,而是调用os.pipe()
,它返回两个通过公共缓冲区连接的新文件描述符。 在这一点上,该进程的父级标准输出stdout,标准错误stderr,以及一个将成为“a标准输出”和“b标准输入”的文件。
叉一个孩子。 孩子用新的stdout替换它的stdout。 执行a
过程。
b关闭的孩子用新的b的stdin替换它的stdin。 执行b
过程。
b孩子等待完成。
父母正在等待b完成。
我认为上述可以递归地用于产生a | b | c
a | b | c
a | b | c
,但是你必须隐式地加长长管道,把它们看作是a | (b | c)
a | (b | c)
。
由于Python有os.pipe()
, os.exec()
和os.fork()
,你可以替换sys.stdin
和sys.stdout
,所以有一种方法可以在纯Python中完成上述操作。 事实上,你可以制定出使用一些快捷键os.pipe()
和subprocess.Popen
。
但是,将该操作委托给shell更容易。
import subprocess
some_string = b'input_data'
sort_out = open('outfile.txt', 'wb', 0)
sort_in = subprocess.Popen('sort', stdin=subprocess.PIPE, stdout=sort_out).stdin
subprocess.Popen(['awk', '-f', 'script.awk'], stdout=sort_in,
stdin=subprocess.PIPE).communicate(some_string)
模拟shell管道:
from subprocess import check_call
check_call('echo "input data" | a | b > outfile.txt', shell=True)
而无需调用外壳(请参阅17.1.4.2。替换外壳管道):
#!/usr/bin/env python
from subprocess import Popen, PIPE
a = Popen(["a"], stdin=PIPE, stdout=PIPE)
with a.stdin:
with a.stdout, open("outfile.txt", "wb") as outfile:
b = Popen(["b"], stdin=a.stdout, stdout=outfile)
a.stdin.write(b"input data")
statuses = [a.wait(), b.wait()] # both a.stdin/stdout are closed already
plumbum
提供了一些语法糖:
#!/usr/bin/env python
from plumbum.cmd import a, b # magic
(a << "input data" | b > "outfile.txt")()
类比:
#!/bin/sh
echo "input data" | awk -f script.awk | sort > outfile.txt
是:
#!/usr/bin/env python
from plumbum.cmd import awk, sort
(awk["-f", "script.awk"] << "input data" | sort > "outfile.txt")()
链接地址: http://www.djcxy.com/p/13471.html
上一篇: How do I use subprocess.Popen to connect multiple processes by pipes?