4

我的问题更多的是理论而不是实际,我找到了更多的答案来解释我们如何而不是为什么subprocess.Popen我们应该在通话中使用列表。

例如众所周知:

Python 2.7.10 (default, Oct 14 2015, 16:09:02)
[GCC 5.2.1 20151010] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> cmd = subprocess.Popen(["python", "-V"], stdout=subprocess.PIPE)
Python 2.7.10

然后我在 UNIX 中乱搞,发现了一些有趣的东西:

mvarge@ubuntu:~$ strace -f python -V 2>&1
execve("/usr/bin/python", ["python", "-V"], [/* 29 vars */]) = 0

可能两者execve和使用的列表模型subprocess都在某种程度上相关,但是任何人都可以对此给出一个很好的解释吗?

提前致谢。

4

2 回答 2

3

底层的 C 级表示是一个*char []数组。在 Python 中将其表示为一个列表只是一个非常自然和透明的映射。

您可以使用字符串而不是带有shell=True;的列表。然后 shell 负责将命令行解析为一个* char []数组。然而,shell 增加了许多令人讨厌的复杂性。请参阅许多问题,了解为什么要避免shell=True详细说明。

命令行参数argv和环境envp只是许多操作系统级结构中的两个,它们本质上是一个以空字符结尾的字符串数组。

于 2016-03-31T12:11:16.490 回答
3

进程是操作系统级别的抽象——要创建进程,您必须使用指示您应该使用什么的操作系统 API。不必使用列表,例如,字符串 ( ) 是Windows ( )lpCommandLine上的本机接口。POSIX 使用 execv(),因此本机接口是一系列参数 ( )。自然地,Python 模块使用这些接口来运行外部命令(创建新进程)。CreateProcess()argvsubprocess

技术(无趣)的答案是,在“为什么我们必须”中,“必须”部分并不像 Windows 所展示的那样正确。

要了解“为什么会这样,您可以询问CreateProcess(),execv()函数的创建者。

要了解“为什么我们应该”使用列表,请查看 Unix(列表)和 Windows(字符串)的目录:如何解析命令行参数——在 Windows 上应该很简单的任务却很复杂。

主要区别在于,在 POSIX 上,调用者负责将命令行拆分为单独的参数。而在 Windows 上,命令本身会解析其参数。不同的程序可能并且确实使用不同的算法来解析参数。subprocess模块使用 MS C 运行时规则 ( subprocess.list2cmdline()),将args列表组合到命令行中。程序员要理解在 Windows 上如何解析参数要困难得多。

于 2016-03-31T18:53:44.603 回答