Python - 如何用管道调用bash命令?

Gre*_*reg 12 python subprocess popen

我可以在Linux的命令行中正常运行:

$ tar c my_dir | md5sum
Run Code Online (Sandbox Code Playgroud)

但是当我尝试用Python调用它时出现错误:

>>> subprocess.Popen(['tar','-c','my_dir','|','md5sum'],shell=True)
<subprocess.Popen object at 0x26c0550>
>>> tar: You must specify one of the `-Acdtrux' or `--test-label'  options
Try `tar --help' or `tar --usage' for more information.
Run Code Online (Sandbox Code Playgroud)

mde*_*ous 14

您还必须使用subprocess.PIPE拆分命令,shlex.split()在某些情况下应该用来防止奇怪的行为:

from subprocess import Popen, PIPE
from shlex import split
p1 = Popen(split("tar -c mydir"), stdout=PIPE)
p2 = Popen(split("md5sum"), stdin=p1.stdout)
Run Code Online (Sandbox Code Playgroud)

但是要创建存档并生成其校验和,您应该使用Python内置模块tarfilehashlib不是调用shell命令.


Gre*_*reg 5

好的,我不确定为什么,但这似乎可行:

subprocess.call("tar c my_dir | md5sum",shell=True)
Run Code Online (Sandbox Code Playgroud)

有人知道为什么原始代码不起作用吗?

  • 管道| 是外壳程序理解为将命令输入和输出连接在一起的字符。它不是tar可以理解的参数,也不是命令。您正在尝试将所有内容作为tar命令的参数执行,除非您创建子外壳。 (2认同)
  • 之所以有效,是因为整个命令都传递给了 *shell*,而 *shell* 理解了 `|`。Popen 调用进程并直接传入参数。对于 Popen,这由 `shell=` 控制并传递一个字符串(不是列表),IIRC。 (2认同)