使用时subprocess.Popen(args, shell=True)
跑步 ”gcc --version
“(仅作为示例),在 Windows 上我们得到:
>>> from subprocess import Popen
>>> Popen(['gcc', '--version'], shell=True)
gcc (GCC) 3.4.5 (mingw-vista special r3) ...
所以它很好地打印出了我所期望的版本。但在 Linux 上我们得到这个:
>>> from subprocess import Popen
>>> Popen(['gcc', '--version'], shell=True)
gcc: no input files
因为gcc还没有收到--version
option.
文档没有具体说明 Windows 下的 args 应该发生什么,但它确实说,在 Unix 上,“如果 args 是一个序列,则第一项指定命令字符串,任何附加项将被视为附加 shell 参数。”恕我直言,Windows 方式更好,因为它允许您处理Popen(arglist)
调用相同Popen(arglist, shell=True)
ones.
为什么 Windows 和 Linux 之间存在差异?
实际上在 Windows 上,它确实使用cmd.exe
when shell=True
- 它前置cmd.exe /c
(它实际上查找COMSPEC
环境变量,但默认为cmd.exe
如果不存在)到 shell 参数。 (在 Windows 95/98 上它使用中间w9xpopen
程序实际启动命令)。
所以奇怪的实现实际上是UNIX
一个,它执行以下操作(其中每个空格分隔不同的参数):
/bin/sh -c gcc --version
看起来正确的实现(至少在 Linux 上)是:
/bin/sh -c "gcc --version" gcc --version
因为这将从引用的参数中设置命令字符串,并成功传递其他参数。
来自sh
手册页部分-c
:
Read commands from the command_string operand instead of from the standard input. Special parameter 0 will be set from the command_name operand and the positional parameters ($1, $2, etc.) set from the remaining argument operands.
这个补丁似乎相当简单地解决了这个问题:
--- subprocess.py.orig 2009-04-19 04:43:42.000000000 +0200
+++ subprocess.py 2009-08-10 13:08:48.000000000 +0200
@@ -990,7 +990,7 @@
args = list(args)
if shell:
- args = ["/bin/sh", "-c"] + args
+ args = ["/bin/sh", "-c"] + [" ".join(args)] + args
if executable is None:
executable = args[0]
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)