当前位置: 首页 > 面试题库 >

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

潘银龙
2023-03-14
问题内容

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上,它确实使用cmd.exe时间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]


 类似资料:
  • 问题内容: 我有一个很长的单行shell命令,将由Python调用。代码如下: 这些代码有效,但始终会这样抱怨: 根据先前的答案,我需要使用更长的脚本来完成此操作,例如: 我的问题是: (1)“第二种方式”是否会比“第一种方式”慢 (2)如果无论如何我都必须以“第一种方式”写(因为这样写起来更快),如何避免这样的抱怨 (3)我不应该以“第一方式”写作的最令人信服的原因是什么 问题答案: 如果您的输

  • 问题内容: 我想知道子句中和值之间的区别。当我使用而不是时,为什么会给我一个编译错误(一个值可能尚未初始化)。 下面是我的代码: 问题答案: 简短答案 对于编译器,可以推断出在读取之前已初始化的内容。这并非如此。 正式答案: 在读取之前, 所有局部变量都必须有一个 确定的赋值 (14.4.2。局部变量声明的执行): […]如果声明符没有初始化表达式, 则对变量的每次引用都必须在对变量的赋值之前执行

  • 问题内容: 有没有一种方法可以终止以subprocess.Popen类开头且“ shell”参数设置为“ True”的进程?在下面的最小工作示例(使用wxPython)中,您可以愉快地打开和终止记事本进程,但是,如果将Popen的“ shell”参数更改为“ True”,则记事本进程不会终止。 为了这个问题,请接受“ shell”必须等于“ True”。 问题答案: 根据Thomas Watned

  • 问题内容: 我正在尝试执行此命令 和 都不起作用(返回空白输出) 有人知道为什么吗? 问题答案: 因为top是一个交互式程序,旨在在终端上运行,而不是从脚本中执行。您可能需要运行带有参数的“ ps”命令,这些命令将按cpu利用率对输出进行排序。 http://www.devdaily.com/linux/unix-linux-process-memory-sort-ps-command- cpu

  • 下面是示例代码。执行的结果不同于jdk@11和jdk@17.将BigDecimal(1000)格式化为字符串后,白色字符看起来有所不同。最后,结果看起来是一样的——但是,它不是相同的字符串(比较bytes和Base64.encoded)。 jdk@11的结果不同于jdk@17 jdk@11结果: jdk@17结果: jdk@11: jdk@17: 系统: 这是预期行为吗?

  • 问题内容: 我用Java创建了一个简单的程序: 如果我在Linux机器上运行此程序,它会显示100%的CPU使用率,但不会导致操作系统显示缓慢。但是,如果我在Windows上运行完全相同的代码,则仅显示约20%的CPU使用率。 我在Windows上使用Oracle JRE,在Linux上使用OpenJDK 6。 我想知道Windows的调度程序是否会随机抢占线程,而Linux的不是吗? 问题答案: