【问题标题】:Why we must use a list in subprocess.Popen?为什么我们必须在 subprocess.Popen 中使用列表?
【发布时间】:2016-03-31 12:00:09
【问题描述】:

我的问题更多的是理论而不是实际,我找到了更多解释如何而不是为什么我们应该在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

execvesubprocess 使用的列表模型可能都在某种程度上相关,但是谁能对此给出一个很好的解释?

提前致谢。

【问题讨论】:

  • 这很方便,一方面。当您的参数包含一个空格和两种不同类型的引号时,需要相当多的时间才能将其放入字符串中,以便 Bash 将其视为一个参数。当它在列表中时,Popen 会为您处理。
  • 顺便说一句,您通常不应该使用subprocess.Popen() - 它在某些平台上的某些情况下恰好可以工作,但在一般情况下,它只是启动一个子进程,并且您需要几个额外的交互才能正确运行和关闭该过程。 subprocess 库中的包装器会处理这一点,并保护您免受底层复杂性的影响——只有当它们不足以满足您的需求时,您才应该转向底层的主力函数。在这种情况下,subprocess.call() 将是首选工具。

标签: python subprocess execve


【解决方案1】:

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

shell=True 可以使用字符串而不是列表;然后shell 负责将命令行解析为* char [] 数组。然而,shell 增加了许多令人讨厌的复杂性。有关详细说明,请参阅why you want to avoid shell=True 的许多问题。

command line arguments argv and the environment envp 只是许多操作系统级结构中的两个,它们本质上是一个以 null 结尾的字符串数组。

【讨论】:

    【解决方案2】:

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

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

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

    要了解“为什么我们应该”使用列表,请查看 Unix(列表)和 Windows(字符串)的目录:How Command Line Parameters Are Parsed — 应该简单的任务很复杂在 Windows 上。

    主要区别在于在 POSIX 上调用者负责将命令行拆分为单独的参数。 在 Windows 上,命令本身会解析其参数。不同的程序可能并且确实使用不同的算法来解析参数。 subprocess module uses MS C runtime rules (subprocess.list2cmdline()), to combine args list into the command line。程序员很难理解在 Windows 上如何解析参数。

    【讨论】:

      猜你喜欢
      • 2020-02-14
      • 2017-09-12
      • 2021-12-12
      • 2013-05-22
      • 1970-01-01
      • 2020-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多