【问题标题】:subprocess.Popen gives random resultsubprocess.Popen 给出随机结果
【发布时间】:2014-05-19 10:14:42
【问题描述】:

我写了一段简单的代码:

import subprocess
p=subprocess.Popen('mkdir -p ./{a,b,c}', shell=True, stderr=subprocess.STDOUT)
p.wait()

不幸的是,它并不总是像我期望的那样运行。即,当我在 PC 上运行它时,一切正常(ls -l 给了我三个目录:a、b 和 c)。但是当我的同事在他的桌面上运行它时,他得到......一个名为:'{a,b,c}' 的目录......我们都使用 Python 2.7.3。这是为什么?你会如何解决它?

我试图自己找到答案。根据手册: "args 应该是程序参数序列或单个字符串。默认情况下,如果 args 是序列,则要执行的程序是 args 中的第一项。如果 args 是字符串,则解释取决于平台,如下所述。有关与默认行为的其他差异,请参阅 shell 和可执行参数。除非另有说明,否则建议将 args 作为序列传递。"

所以我尝试在shell中执行代码:

python -c "import subprocess; p=subprocess.Popen(['mkdir', '-p', './{ea,fa,ga}'], shell=True, stderr=subprocess.STDOUT); p.wait()"

我得到了:

mkdir: missing operand

如果您有任何建议,我将不胜感激

谢谢!

【问题讨论】:

  • 您(和您的同事)在什么操作系统上运行它?如果都是linux,你用的是什么shell?
  • 不同的shell可能会给出不同的结果。
  • @endragor 我不认为这是重复的。这个问题是关于./{a,b,c} 语法,而不是mkdir -p 命令本身。

标签: python shell


【解决方案1】:

./{a,b,c} 语法是 bash 语法,并非所有 shell 都支持。

文档说:

在带有shell=True 的Unix 上,shell 默认为/bin/sh。如果 args 是 字符串,字符串指定要通过shell执行的命令。

因此,您的命令仅在 /bin/sh 符号链接到支持该语法的 shell 时才有效,例如 bashzsh。您的同事可能正在使用 dash 或其他不支持此功能的 shell。

您不应该依赖于用户默认 shell 之类的东西。相反,用完整的扩展编写完整的命令:

p = subprocess.Popen('mkdir -p ./a ./b ./c', shell=True, stderr=subprocess.STDOUT)

【讨论】:

    【解决方案2】:

    这里有几个问题。

    • 首先:如果您使用一系列参数,请不要设置“shell = True”(this is recommended in the Popen manual)。将其设置为 False,您会看到您的 mkdir 命令将被接受。
    • "./{a,b,c}" 是 AFAIK bash 中的一种特定语法。如果您的同事使用不同的 shell,它可能无法工作,或者行为不同。
    • 您应该使用 python“mkdir”命令而不是调用 shell 命令,它可以在任何服务器/shell/操作系统中工作。

    【讨论】:

      【解决方案3】:

      谢谢大家的回答。 看来,最好的方法是简单地使用 /bin/sh 语法。我更改了我的代码以使用:

      'mkdir -p ./a ./b ./c'
      

      正如你所建议的那样。

      我避免使用 mkdir() 函数,因为我正在编写一个包含大量系统调用的脚本,并且我想提供优雅的 --dry-run 选项(这样我可以列出所有命令)。

      问题已解决 - 谢谢!

      【讨论】:

        【解决方案4】:

        据我所知,os.mkdir(path,[mode]) 方法在处理多平台项目时使用起来更安全。

        os.mkdir(os.getcwd()/a)
        

        但是它不如采用子流程方法那么优雅。

        【讨论】:

        • 您的代码不起作用,您需要使用引号:os.getcwd() + "/a"。这也不能回答具体的 OP 问题。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-06-11
        • 2022-06-15
        • 2021-08-30
        • 2017-04-12
        • 2012-05-16
        • 1970-01-01
        相关资源
        最近更新 更多