在 Python 中可以使用 subprocess 模块执行 shell 命令。在执行 shell 命令时不能使用一条 subprocess 的函数,在命令的内部使用 shell 内置的管道符 “|”;而是使用 subprocess 模块一次执行一个命令,使用 subprocess 模块提供的管道 subprocess.PIPE 连接多个命令。

文本将介绍在 Python 中使用 subprocess 模块执行 shell 命令时 subprocess.PIPE 管道的使用方法。

使用 Popen 配合 PIPE 管道执行多条命令

使用 subprocess.Popen 构造的函数可以实现非阻塞执行,即在 subprocess.Popen 执行的过程中输出执行结果;当然也能实现阻塞执行,即当进程执行完毕后,再输出执行结果。

使用 PIPE 管道连接多条命令使用说明:

  • 上一条命令需要使用 stdout 参数把该条命令的输出内容写入 subprocess.PIPE
  • 下一条命令需要使用 stdin 参数从上条命令 stdout 读取内容

使用 Popen 配合 PIPE 阻塞执行多条命令

使用 subprocess.Popen 构造的函数实现非阻塞执行,在 subprocess.Popen 执行的过程中输出执行结果示例:

# popen_pipe.py

import subprocess

ls_process = subprocess.Popen(["ls", "/usr/bin"], stdout=subprocess.PIPE)
grep_process = subprocess.Popen(
    ["grep", "python"], stdin=ls_process.stdout, stdout=subprocess.PIPE
)
outputs, errors = proc.communicate()
print(outputs)

使用 Popen 配合 PIPE 非阻塞执行多条命令

使用 subprocess.Popen 构造的函数实现非阻塞执行,在 subprocess.Popen 执行的过程中输出执行结果示例:

# popen_pipe.py

import subprocess

ls_process = subprocess.Popen(["ls", "/usr/bin"], stdout=subprocess.PIPE)
grep_process = subprocess.Popen(
    ["grep", "python"], stdin=ls_process.stdout, stdout=subprocess.PIPE
)

for line in grep_process.stdout:
    print(line.decode("utf-8").strip())

使用 subprocess.run 模拟 PIPE 管道执行多条命令

虽然不能通过使用 subprocess.run() 函数将两个进程用管道连接在一起,但是可以使用 stdout 属性来模拟管道。

如果你在基于 Unix 的系统上,那么你可以将第二个进程的输入设置为第一个 CompletedProcess(subprocess.run() 函数的返回值) 的 .stdout 属性。

模拟 PIPE 管道连接多条命令使用说明:

  • 上一条命令需要使用 stdout 参数把该条命令的输出内容写入 subprocess.PIPE
  • 下一条命令需要使用 input 参数从上条命令 stdout 读取内容

使用 subprocess.run 模拟 PIPE 管道执行多条命令示例:

import subprocess
ls_process = subprocess.run(["ls", "/usr/bin"], stdout=subprocess.PIPE)
grep_process = subprocess.run(
    ["grep", "python"], input=ls_process.stdout, stdout=subprocess.PIPE
)
print(grep_process.stdout.decode("utf-8"))

结语

本文介绍了在 Python 中使用 subprocess 模块执行 shell 命令时 subprocess.PIPE 管道的使用方法。分别介绍了使用 subprocess.Popen 配合 PIPE 管道执行多条命令和使用 subprocess.run 模拟 PIPE 管道执行多条命令。