【问题标题】: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

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

【问题讨论】:

标签: python subprocess pipe


【解决方案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 结果中,我怎么能得到错误?这是我的问题,你能帮忙吗? stackoverflow.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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-05-05
        • 1970-01-01
        • 1970-01-01
        • 2018-12-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多