Python 子进程:使用 subprocess.run 链接命令

Chr*_*ark 4 subprocess python-3.x python-3.5

我正在 Python 3.5 中试验subprocess.run。要将两个命令链接在一起,我认为以下应该有效:

import subprocess

ps1 = subprocess.run(['ls'], universal_newlines=True, stdout=subprocess.PIPE)
ps2 = subprocess.run(['cowsay'], stdin=ps1.stdout)
Run Code Online (Sandbox Code Playgroud)

但是,这会失败:

AttributeError: 'str' object has no attribute 'fileno'
Run Code Online (Sandbox Code Playgroud)

ps2期待一个类似文件的对象,但输出ps1是一个简单的字符串。

有没有办法将命令链接在一起subprocess.run?

jfs*_*jfs 6

subprocess.run()不能ls | cowsay在没有 shell 的情况下实现,因为它不允许同时运行各个命令:每个subprocess.run()调用都会等待进程完成,这就是它返回CompletedProcess对象的原因(请注意此处的“完成”一词)。ps1.stdout在您的代码中是一个字符串,这就是为什么您必须将其作为input而不是stdin需要文件/管道的参数传递(有效.fileno())。

要么使用外壳:

subprocess.run('ls | cowsay', shell=True)
Run Code Online (Sandbox Code Playgroud)

或者使用subprocess.Popen, 来同时运行子进程:

from subprocess import Popen, PIPE

cowsay = Popen('cowsay', stdin=PIPE)
ls = Popen('ls', stdout=cowsay.stdin)
cowsay.communicate()
ls.wait()
Run Code Online (Sandbox Code Playgroud)

请参阅如何使用 subprocess.Popen 通过管道连接多个进程?

  • @ChrisClark:你明白以下之间的区别吗:`ls | owsay` 和 `output=$(ls); 牛说<<<“$output”`? (2认同)

Chr*_*ark 5

事实证明subprocess.run有一个input参数可以处理这个问题:

ps1 = subprocess.run(['ls'], universal_newlines=True, stdout=subprocess.PIPE)
ps2 = subprocess.run(['cowsay'], universal_newlines=True, input=ps1.stdout)
Run Code Online (Sandbox Code Playgroud)

另外,以下内容也有效,但不使用input:

ps1 = subprocess.run(['ls'], universal_newlines=True, stdout=subprocess.PIPE)
ps2 = subprocess.run(['cowsay', ps1.stdout], universal_newlines=True)
Run Code Online (Sandbox Code Playgroud)