subprocess.Popen给出随机结果

时间:2014-05-19 10:14:42

标签: python shell

我写了一段简单的代码:

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

不幸的是,它并不总是像我期望的那样。即,当我在我的电脑上运行它时,一切都很好(ls -l给了我三个dirs: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

我会感谢任何建议

谢谢!

4 个答案:

答案 0 :(得分:2)

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

文档说:

  

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

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

你不应该依赖用户的默认shell。相反,使用完整扩展编写完整命令:

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

答案 1 :(得分:0)

这里有几个问题。

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

答案 2 :(得分:0)

谢谢大家的回答。 看来,最好的方法就是使用/ bin / sh语法。我改变了我的代码使用:

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

正如你的建议。

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

问题解决了 - 谢谢!

答案 3 :(得分:-1)

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

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

然而,它并不像采用子流程方法那样优雅。