用pipe道连接几个Popen命令

我知道如何运行命令使用cmd = subprocess.Popen,然后subprocess.communicate。 大多数情况下,我使用一个用shlex.split标记的string作为Popen的“argv”参数。 “ls -l”的例子:

import subprocess import shlex print subprocess.Popen(shlex.split(r'ls -l'), stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE).communicate()[0] 

但是,pipe道似乎不工作…例如,下面的示例返回注意:

 import subprocess import shlex print subprocess.Popen(shlex.split(r'ls -l | sed "s/a/b/g"'), stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE).communicate()[0] 

你能告诉我我做错了吗?

谢谢

我想你想在这里实例化两个单独的Popen对象,一个用于'ls',另一个用于'sed'。 你需要将第一个Popen对象的stdout属性作为stdinparameter passing给第二个Popen对象。

例:

 p1 = subprocess.Popen('ls ...', stdout=subprocess.PIPE) p2 = subprocess.Popen('sed ...', stdin=p1.stdout, stdout=subprocess.PIPE) print p2.communicate() 

如果你有更多的命令,你可以保持这种方式:

 p3 = subprocess.Popen('prog', stdin=p2.stdout, ...) 

有关如何使用子stream程的更多信息,请参阅子stream程文档 。

shlex只根据shell规则分割空间,但不处理pipe道。

但是,它应该这样工作:

 import subprocess import shlex sp_ls = subprocess.Popen(shlex.split(r'ls -l'), stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE) sp_sed = subprocess.Popen(shlex.split(r'sed "s/a/b/g"'), stdin = sp_ls.stdout, stdout = subprocess.PIPE, stderr = subprocess.PIPE) sp_ls.stdin.close() # makes it similiar to /dev/null output = sp_ls.communicate()[0] # which makes you ignore any errors. print output 

根据help(subprocess)

 Replacing shell pipe line ------------------------- output=`dmesg | grep hda` ==> p1 = Popen(["dmesg"], stdout=PIPE) p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) output = p2.communicate()[0] 

HTH

我已经做了一些帮助pipe道的function,希望它有帮助。 它将根据需要链接Popens。

 from subprocess import Popen, PIPE import shlex def run(cmd): """Runs the given command locally and returns the output, err and exit_code.""" if "|" in cmd: cmd_parts = cmd.split('|') else: cmd_parts = [] cmd_parts.append(cmd) i = 0 p = {} for cmd_part in cmd_parts: cmd_part = cmd_part.strip() if i == 0: p[i]=Popen(shlex.split(cmd_part),stdin=None, stdout=PIPE, stderr=PIPE) else: p[i]=Popen(shlex.split(cmd_part),stdin=p[i-1].stdout, stdout=PIPE, stderr=PIPE) i = i +1 (output, err) = p[i-1].communicate() exit_code = p[0].wait() return str(output), str(err), exit_code output, err, exit_code = run("ls -lha /var/log | grep syslog | grep gz") if exit_code != 0: print "Output:" print output print "Error:" print err # Handle error here else: # Be happy :D print output 

“”“你为什么不用shell呢

“””

def output_shell(line):

 try: shell_command = Popen(line, stdout=PIPE, stderr=PIPE, shell=True) except OSError: return None except ValueError: return None (output, err) = shell_command.communicate() shell_command.wait() if shell_command.returncode != 0: print "Shell command failed to execute" return None return str(output)