Python子进程:如何使用管道三次?

Zor*_*zyd 11 python subprocess pipe

我想在以下行使用子进程:

convert ../loxie-orig.png bmp:- | mkbitmap -f 2 -s 2 -t 0.48 | potrace -t 5 --progress -s -o ../DSC00232.svg
Run Code Online (Sandbox Code Playgroud)

我感谢其他帖子的子流程文档,但在示例中我们只使用了两次管道.

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

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]
Run Code Online (Sandbox Code Playgroud)

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

非常感谢你.

Hun*_*len 21

只需按照相同的示例添加第三个命令:

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]
Run Code Online (Sandbox Code Playgroud)

  • 如果`p1.stdout.close()`和`p2.stdout.close()`来自`output = p3.communicate()[0]`之后是否重要? (3认同)

ale*_*xis 5

subprocess.Popen()与选项一起使用shell=True,您可以将整个命令作为单个字符串传递给它.

  • 这通常是可行的方法(它肯定要容易得多),但有时您可能会遇到文件名引用问题,例如,在这里,如果“fileIn”或“fileOut”名称中包含空格。大多数情况下可以使用“pipes.quote”来处理这些问题,但保留“shell=False”在技术上更安全。 (3认同)

dan*_*god 5

def runPipe(cmds):
try: 
    p1 = subprocess.Popen(cmds[0].split(' '), stdin = None, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    prev = p1
    for cmd in cmds[1:]:
        p = subprocess.Popen(cmd.split(' '), stdin = prev.stdout, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
        prev = p
    stdout, stderr = p.communicate()
    p.wait()
    returncode = p.returncode
except Exception, e:
    stderr = str(e)
    returncode = -1
if returncode == 0:
    return (True, stdout.strip().split('\n'))
else:
    return (False, stderr)
Run Code Online (Sandbox Code Playgroud)

然后像这样执行:

runPipe(['ls -1','head -n 2', 'head -n 1'])
Run Code Online (Sandbox Code Playgroud)