Python - 如何使用管道执行shell命令,但没有'shell = True'?

Posted

技术标签:

【中文标题】Python - 如何使用管道执行shell命令,但没有\'shell = True\'?【英文标题】:Python - how to execute shell commands with pipe, but without 'shell=True'?Python - 如何使用管道执行shell命令,但没有'shell = True'? 【发布时间】:2012-03-12 16:47:55 【问题描述】:

我有一个案例想在 Python 中执行以下 shell 命令并获取输出,

echo This_is_a_testing | grep -c test

我可以使用这个python代码在python中执行上面的shell命令,

>>> import subprocess
>>> subprocess.check_output("echo This_is_a_testing | grep -c test", shell=True)
'1\n'

但是,由于我不想使用“shell=True”选项,我尝试了以下 python 代码,

>>> import subprocess
>>> p1 = subprocess.Popen(["echo", "This_is_a_testing"], stdout=subprocess.PIPE)
>>> p2 = subprocess.Popen(["grep", "-c", "test"], stdin=p1.stdout)
>>> p1.stdout.close()
>>> p2.communicate()
(None, None)

我想知道为什么输出是“无”,因为我参考了网页中的描述:http://docs.python.org/library/subprocess.html#subprocess.PIPE

我是否遗漏了代码中的一些要点?有什么建议/想法吗?提前致谢。

【问题讨论】:

相关:How do I use subprocess.Popen to connect multiple processes by pipes? 【参考方案1】:

请看这里:

>>> import subprocess
>>> p1 = subprocess.Popen(["echo", "This_is_a_testing"], stdout=subprocess.PIPE)
>>> p2 = subprocess.Popen(["grep", "-c", "test"], stdin=p1.stdout)
>>> 1
p1.stdout.close()
>>> p2.communicate()
(None, None)
>>>

在你写p2 = subprocess.Popen(["grep", "-c", "test"], stdin=p1.stdout) 之后,这里你得到 1 作为输出,不要在你的问题的上下文中忽略这个输出。

如果这是您想要的,则将stdout=subprocess.PIPE 作为参数传递给第二个Popen

>>> p1 = subprocess.Popen(["echo", "This_is_a_testing"], stdout=subprocess.PIPE)
>>> p2 = subprocess.Popen(["grep", "test"], stdin=p1.stdout, stdout=subprocess.PIPE)
>>> p2.communicate()
('This_is_a_testing\n', None)
>>>

【讨论】:

现在我知道要让p2.communicate() 工作,我必须在代码p2 = ... 中添加stdout=subprocess.PIPE。谢谢。 如果它发生在 p1 结果中,我怎么能得到错误?这是我的问题,你能帮忙吗? ***.com/questions/40467105/…【参考方案2】:
>>> import subprocess

>>> mycmd=subprocess.getoutput('df -h | grep home | gawk \' print $1 \' | cut -d\'/\' -f3')

>>> mycmd 

'sda6'

>>>

【讨论】:

它在内部使用 shell。 OP 明确表示:“我不想使用“shell=True”选项” 谢谢。这正是我在 Python 中搜索“如何使用管道执行 shell 命令”时要寻找的内容。 我必须使用 commands.getoutput 而不是 subprocess.getoutput 才能工作 不是subprocess.check_output() 在 Python 2.7 中不存在,在 Python 3.6.6 中存在【参考方案3】:

来自手册:

要在结果元组中获得除 None 以外的任何内容,您需要给出 stdout=PIPE 和/或 stderr=PIPE

p2 = subprocess.Popen(["grep", "-c", "test"], stdin=p1.stdout, stdout=subprocess.PIPE)

【讨论】:

【参考方案4】:

虽然接受的答案正确/有效,但另一种选择是使用 Popen.communicate() 方法将某些内容传递给进程的标准输入:

>>> import subprocess
>>> p2 = subprocess.Popen(["grep", "-c", "test"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
>>> p2.communicate("This_is_a_testing")
('1\n', None)
>>> print p2.returncode
0
>>>>

这解决了执行另一个命令来重定向它的输出的需要,如果输出在 python 脚本本身中是已知的。

但是communicate 有副作用,它会等待进程终止。如果需要/希望使用两个进程异步执行可能是更好的选择。

【讨论】:

【参考方案5】:

答案与前面提到的类似,格式很少。我想在 python 3 上使用管道获得与普通 shell 命令完全相同的输出。

import subprocess

p1 = subprocess.Popen(["ls", "-l", "."], stdout=subprocess.PIPE)
p2 = subprocess.Popen(["grep", "May"], stdin=p1.stdout, stdout=subprocess.PIPE)


for s in (str(p2.communicate())[2:-10]).split('\\n'):
    print(s)

【讨论】:

以上是关于Python - 如何使用管道执行shell命令,但没有'shell = True'?的主要内容,如果未能解决你的问题,请参考以下文章

Python中带有管道的Shell命令[重复]

Shell编程之多命令顺序执行和管道符

如何从 Java 调用 Linux shell 命令

如何从 Java 调用 Linux shell 命令

管道符和作业控制shell变量环境变量配置文件

linux shell脚本执行命令时创建子进程问题(特定的情况,例如后台运行管道分支或子shell等,脚本可能会创建子进程执行命令)