python - 为什么带有 shell=True 的 subprocess.Popen() 在 Linux 和 Windows 上的工作方式不同?

标签 python shell subprocess popen

当使用 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选项。

文档没有具体说明在 Windows 下 args 应该发生什么,但它确实说,在 Unix 上,“如果 args 是一个序列,第一项指定命令字符串,任何附加项将被视为额外的 shell 参数。” 恕我直言,Windows 方式更好,因为它允许您将 Popen(arglist) 调用与 Popen(arglist, shell=True ) 个。

为什么这里有 Windows 和 Linux 的区别?

最佳答案

实际上在 Windows 上,当 shell=True 时它确实使用 cmd.exe - 它预先添加 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

因为这会从引用的参数中设置命令字符串,并成功传递其他参数。

来自 -csh 手册页部分:

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]

关于python - 为什么带有 shell=True 的 subprocess.Popen() 在 Linux 和 Windows 上的工作方式不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1253122/

相关文章:

python - 索引 0 超出了大小为 0 的轴 0 的范围

python try except yield 组合

python - 如何获取子进程的 stderr 流输出的最后 N 行?

python - 使用子进程模块通过 SSH 连接 Linux 盒子

python - 点击后抓取 .aspx 网站

python - 如何在不分割数据的情况下运行sklearn.model_selection.GridSearchCV?

r - 指定在 R 中使用哪个 shell

regex - 如何使用 grep 对多个文本字符串进行反向搜索

bash - 如何对名称中包含空格的文件执行 shell "for"命令?

python - 使用 django 运行带有密码参数的 python 脚本