【问题标题】:python Popen shell=True behaviorpython Popen shell=真实行为
【发布时间】:2026-01-06 12:40:01
【问题描述】:

为什么这不起作用:subprocess.Popen(["ls -l | grep myfile"], shell=False) 但是这条线有效:subprocess.Popen(["ls -l | grep myfile"], shell=True) 我理解这个 shell=True 在内部创建一个子 shell 并执行命令。但不明白这如何影响 Popen 行为

【问题讨论】:

  • 试试subprocess.Popen(["ls", "-l", "|", "grep", "shell"], shell=False)
  • 我的目的是了解 Popen 的行为,而不是让它发挥作用。求解释
  • 它不会像预期的那样工作,因为它会假设'|','grep'和'shell'文件名,@Abhishek

标签: python python-3.x subprocess


【解决方案1】:

Popen() 使用子进程模块内的代码进行子进程管理。它不知道使用| 进行管道传输,也不知道您传递的字符串是程序还是参数,就像在您使用ls 的示例中一样,它将假定除ls 本身之外的所有其他内容都是程序的参数。它将尝试执行列表中的第一项并将所有其他项作为参数传递。

当您使用 shell=True 时,您可能会认为它(例如在 UNIX 上)运行 /bin/sh -c 并带有您作为字符串提供的 arglist。所以

Popen('ls -l | grep myfile', shell=True)

很接近

Popen(['/bin/sh', '-c', 'ls -l | grep myfile'])

在这两种情况下,参数处理实际上都是由你的 shell 完成的。

对于管道和shell=False,您应该使用subprocess.PIPE 和stdout/stdin/stderr 重定向以及子流程模块中提供的工具。

【讨论】:

    【解决方案2】:

    shell=True 用于将单个 string 作为命令行传递给 shell。虽然在技术上可以传递一个列表,但它可能永远不是你想要的。

    subprocess.Popen("ls -l | grep myfile", shell=True)
    

    【讨论】:

      【解决方案3】:

      如果你使用shell=False,你一定要喜欢它:

      subprocess.Popen(["ls","-l"],shell=False)
      

      【讨论】:

        最近更新 更多