subprocess.Popen gives random result
我写了一段简单的代码:
1 2 3 | import subprocess p=subprocess.Popen('mkdir -p ./{a,b,c}', shell=True, stderr=subprocess.STDOUT) p.wait() |
不幸的是,它并不总是如我所料。也就是说,当我在PC上运行它时,一切都正常(ls-l给了我三个dirs:a、b和c)。但是当我的同事在他的桌面上运行它时,他会…一个名为"A、B、C"的目录。我们都使用python 2.7.3。为什么会这样?你将如何修复它?
我试图自己找到答案。根据手册:"args应该是程序参数序列,或者是单个字符串。默认情况下,如果args是序列,则要执行的程序是args中的第一个项。如果args是字符串,则解释取决于平台,如下所述。有关与默认行为的其他差异,请参阅shell和可执行参数。除非另有说明,建议按顺序传递参数。"
所以我尝试在shell中执行代码:
1 | python -c"import subprocess; p=subprocess.Popen(['mkdir', '-p', './{ea,fa,ga}'], shell=True, stderr=subprocess.STDOUT); p.wait()" |
我得到了:
1 | mkdir: missing operand |
我会感谢你的任何建议
谢谢!
文件上说:
On Unix with
shell=True , the shell defaults to/bin/sh . If args is a
string, the string specifies the command to execute through the shell.
因此,只有当
您不应该依赖于用户的默认shell。相反,使用完全扩展编写完整命令:
1 | p = subprocess.Popen('mkdir -p ./a ./b ./c', shell=True, stderr=subprocess.STDOUT) |
谢谢大家的回答。似乎最好的方法就是简单地使用/bin/sh语法。我将代码更改为使用:
1 | 'mkdir -p ./a ./b ./c' |
如你所建议的。
我避免使用mkdir()函数,因为我正在编写一个包含大量系统调用的脚本,并且我希望提供优雅的--dry-run选项(这样我可以列出所有命令)。
问题解决了-谢谢!
这里有几个问题。
- 首先:如果您使用的是一系列参数,请不要设置"shell=true"(这在popen手册中是推荐的)。将其设置为false,您将看到mkdir命令将被接受。
- "/a,b,c"是bash中的特定语法。如果你的同事使用了不同的外壳,它可能不会工作,也不会表现得不同。
- 您应该使用python"mkdir"命令,而不是调用shell命令,无论服务器/shell/OS是什么,它都可以工作。
据我所知,mkdir(path,[mode])方法在处理多平台项目时更安全。
1 | os.mkdir(os.getcwd()/a) |
然而,它不如采用子流程方法那么优雅。