"subprocess" --- 子进程管理
***************************

**源代码:** Lib/subprocess.py

======================================================================

The "subprocess" module allows you to spawn new processes, connect to
their input/output/error pipes, and obtain their return codes.  This
module intends to replace several older modules and functions:

   os.system
   os.spawn*

Information about how the "subprocess" module can be used to replace
these modules and functions can be found in the following sections.

参见: **PEP 324** -- 提出 subprocess 模块的 PEP

适用范围: not Android, not iOS, not WASI.

此模块在 移动平台 或 WebAssembly 平台 上不受支持。


使用 "subprocess" 模块
======================

推荐的调用子进程的方式是在任何它支持的用例中使用 "run()" 函数。对于更
进阶的用例，也可以使用底层的 "Popen" 接口。

subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None, text=None, env=None, universal_newlines=None, **other_popen_kwargs)

   运行被 *args* 描述的指令。等待指令完成，然后返回一个
   "CompletedProcess" 实例。

   以上显示的参数仅仅是最简单的一些，下面 常用参数 描述（因此在缩写签
   名中使用仅关键字标示）。完整的函数头和 "Popen" 的构造函数一样，此函
   数接受的大多数参数都被传递给该接口。（*timeout*, *input*, *check*
   和 *capture_output* 除外）。

   如果 *capture_output* 为真值，则 stdout 和 stderr 将被捕获。当被使
   用时，内部 "Popen" 对象将自动创建并把 *stdout* 和 *stderr* 均设为
   "PIPE"。 *stdout* 和 *stderr* 参数不可与 *capture_output* 同时提供
   。如果你希望捕获并将两个流合并在一起，请将 *stdout* 设为 "PIPE" 并
   将 *stderr* 设为 "STDOUT"，而不是使用 *capture_output*.

   可以指定以秒为单位的 *timeout*，它会在内部传递给
   "Popen.communicate()"。 如果达到超时限制，子进程将被杀掉并等待。
   "TimeoutExpired" 异常将在子进程终结后重新被引发。在许多平台 API 上
   初始进程创建本身不可以被打断因此不保证你能看到超时异常直到至少进程
   创建花费的时间结束后。

   *input* 参数将被传递给 "Popen.communicate()" 以及子进程的 stdin。
   如果使用此参数则它必须是一个字节序列，或者如果指定了 *encoding* 或
   *errors* 或 *text* 为真值则可以是一个字符串。 当使用此参数时，将自
   动创建内部的 "Popen" 对象并将其 *stdin* 设为 "PIPE"，并且不可同时使
   用 *stdin* 参数。

   如果 *check* 设为 True, 并且进程以非零状态码退出，一个
   "CalledProcessError" 异常将被抛出。这个异常的属性将设置为参数，退出
   码，以及标准输出和标准错误，如果被捕获到。

   如果指定了 *encoding* 或 *errors*，或者 *text* 被设为真值，标准输入
   、标准输出和标准错误的文件对象将使用指定的 *encoding* 和 *errors*
   或者 "io.TextIOWrapper" 默认值以文本模式打开。 *universal_newlines*
   参数等同于 *text* 并且提供了向后兼容性。默认情况下，文件对象是以二
   进制模式打开的。

   如果 *env* 不为 "None"，则它必须是一个为新进程定义环境变量的映射；
   它们将顶替继承当前进程环境的默认行为被使用。它会被直接传递给
   "Popen"。这个映射在任何平台上均可以是字符串到字符串的映射或者在
   POSIX 平台上也可以是字节串到字节串的映射，就像是 "os.environ" 或者
   "os.environb"。

   示例:

      >>> subprocess.run(["ls", "-l"])  # 不捕获输出
      CompletedProcess(args=['ls', '-l'], returncode=0)

      >>> subprocess.run("exit 1", shell=True, check=True)
      Traceback (most recent call last):
        ...
      subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

      >>> subprocess.run(["ls", "-l", "/dev/null"], capture_output=True)
      CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0,
      stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n', stderr=b'')

   Added in version 3.5.

   在 3.6 版本发生变更: 添加了 *encoding* 和 *errors* 形参。

   在 3.7 版本发生变更: 添加了 *text* 形参，作为 *universal_newlines*
   的一个更好理解的别名。添加了 *capture_output* 形参。

   在 3.12 版本发生变更: 针对 "shell=True" 改变的 Windows shell 搜索顺
   序。当前目录和 "%PATH%" 会被替换为 "%COMSPEC%" 和
   "%SystemRoot%\\System32\\cmd.exe"。因此，在当前目录中投放一个命名为
   "cmd.exe" 的恶意程序不会再起作用。

class subprocess.CompletedProcess

   "run()" 的返回值，代表一个进程已经结束。

   args

      被用作启动进程的参数。可能是一个列表或字符串。

   returncode

      子进程的退出状态码。通常来说，一个为 0 的退出码表示进程运行正常
      。

      一个负值 "-N" 表示子进程被信号 "N" 中断 (仅 POSIX).

   stdout

      从子进程捕获到的标准输出。 一个字节序列，或者如果 "run()" 是设置
      了 *encoding*, *errors* 或者 "text=True" 来运行的则为一个字符串
      。 如果标准输出未被捕获则该值为 "None"。

      如果你通过 "stderr=subprocess.STDOUT" 运行进程，标准输出和标准错
      误将被组合在这个属性中，并且 "stderr" 将为 "None"。

   stderr

      捕获到的子进程的标准错误。 一个字节序列，或者如果 "run()" 是设置
      了参数 *encoding*, *errors* 或者 "text=True" 运行的则为一个字符
      串。 如果标准错误未被捕获则该值为 "None"。

   check_returncode()

      如果 "returncode" 非零，则会抛出 "CalledProcessError" 异常。

   Added in version 3.5.

subprocess.DEVNULL

   可被 "Popen" 的 *stdin*, *stdout* 或者 *stderr* 参数使用的特殊值，
   表示使用特殊文件 "os.devnull".

   Added in version 3.3.

subprocess.PIPE

   可被 "Popen" 的 *stdin*, *stdout* 或者 *stderr* 参数使用的特殊值，
   表示打开标准流的管道。常用于 "Popen.communicate()".

subprocess.STDOUT

   可被 "Popen" 的 *stderr* 参数使用的特殊值，表示标准错误与标准输出使
   用同一句柄。

exception subprocess.SubprocessError

   此模块的其他异常的基类。

   Added in version 3.3.

exception subprocess.TimeoutExpired

   "SubprocessError" 的子类，等待子进程的过程中发生超时时被抛出。

   cmd

      用于创建子进程的指令。

   timeout

      超时秒数。

   output

      当被 "run()" 或 "check_output()" 捕获时的子进程的输出。在其它情
      况下将为 "None"。当有任何输出被捕获时这将始终为 "bytes" 而不考虑
      是否设置了 "text=True"。 当未检测到输出时它可能会保持为 "None"
      而不是 "b''"。

   stdout

      对 output 的别名，对应的有 "stderr"。

   stderr

      当被 "run()" 捕获时的标准错误输出。在其它情况下将为 "None"。当有
      标准错误输出被捕获时这将始终为 "bytes" 而不考虑是否设置了
      "text=True"。当未检测到标准错误输出时它可能会保持为 "None" 而不
      是 "b''"。

   Added in version 3.3.

   在 3.5 版本发生变更: 添加了 *stdout* 和 *stderr* 属性。

exception subprocess.CalledProcessError

   "SubprocessError" 的子类，当一个由 "check_call()", "check_output()"
   或 "run()" (附带 "check=True") 运行的进程返回了非零退出状态码时将被
   引发。

   returncode

      子进程的退出状态。如果程序由一个信号终止，这将会被设为一个负的信
      号码。

   cmd

      用于创建子进程的指令。

   output

      子进程的输出，如果被 "run()" 或 "check_output()" 捕获。否则为
      "None"。

   stdout

      对 output 的别名，对应的有 "stderr"。

   stderr

      子进程的标准错误输出，如果被 "run()" 捕获。否则为 "None"。

   在 3.5 版本发生变更: 添加了 *stdout* 和 *stderr* 属性。


常用参数
--------

为了支持丰富的使用案例， "Popen" 的构造函数（以及方便的函数）接受大量
可选的参数。对于大多数典型的用例，许多参数可以被安全地留以它们的默认值
。通常需要的参数有：

   *args* 被所有调用需要，应当为一个字符串，或者一个程序参数序列。 提
   供一个参数序列通常更好，它可以更小心地使用参数中的转义字符以及引用
   （例如允许文件名中的空格）。 如果传递一个简单的字符串，则 *shell*
   参数必须为 "True" (见下文) 或者该字符串中将被运行的程序名必须用简单
   的命名而不指定任何参数。

   *stdin*, *stdout* 和 *stderr* 分别指定被执行程序的标准输入、标准输
   出和标准错误文件句柄。合法的值包括 "None", "PIPE", "DEVNULL", 现存
   的文件描述符（一个正整数），现存的具有合法文件描述符的 *file
   object*。当使用默认设置 "None" 时，将不会进行任何重定向。 "PIPE" 表
   示应当新建一个连接子进程的管道。 "DEVNULL" 表示将使用特殊文件
   "os.devnull"。此外，*stderr* 还可以为 "STDOUT"，这表示来自子进程的
   stderr 数据应当被捕获到与 *stdout* 相同的文件句柄中。

   如果指定了 *encoding* 或 *errors*，或者 *text* (也称
   *universal_newlines*) 为真，则文件对象 *stdin*、 *stdout* 与
   *stderr* 将会使用在此次调用中指定的 *encoding* 和 *errors* 或者
   "io.TextIOWrapper" 的默认值以文本模式打开。

   当构造函数的 *newline* 参数为 "None" 时。对于 *stdin*，输入的换行符
   "'\\n'" 将被转换为默认的换行符 "os.linesep"。对于 *stdout* 和
   *stderr*，所有输出的换行符都被转换为 "'\\n'"。更多信息，查看
   "io.TextIOWrapper" 类的文档。

   如果文本模式未被使用， *stdin*， *stdout* 和 *stderr* 将会以二进制
   流模式打开。没有编码与换行符转换发生。

   在 3.6 版本发生变更: 增加了 *encoding* 和 *errors* 形参。

   在 3.7 版本发生变更: 添加了 *text* 形参作为 *universal_newlines* 的
   别名。

   备注:

     文件对象 "Popen.stdin"、 "Popen.stdout" 和 "Popen.stderr" 的换行
     符属性不会被 "Popen.communicate()" 方法更新。

   如果 *shell* 设为 "True"，则使用 shell 执行指定的指令。如果您主要使
   用 Python 增强的控制流（它比大多数系统 shell 提供的强大），并且仍然
   希望方便地使用其他 shell 功能，如 shell 管道、文件通配符、环境变量
   展开以及 "~" 展开到用户家目录，这将非常有用。但是，注意 Python 自己
   也实现了许多类似 shell 的特性（例如 "glob", "fnmatch", "os.walk()",
   "os.path.expandvars()", "os.path.expanduser()" 和 "shutil"）。

   在 3.3 版本发生变更: 当 *universal_newlines* 被设为 "True"，则类将
   使用 "locale.getpreferredencoding(False)" 编码格式来代替
   "locale.getpreferredencoding()"。关于它们的区别的更多信息，见
   "io.TextIOWrapper".

   备注:

     在使用 "shell=True" 之前，请阅读 Security Considerations 段落。

这些选项以及所有其他选项在 "Popen" 构造函数文档中有更详细的描述。


Popen 构造函数
--------------

此模块的底层的进程创建与管理由 "Popen" 类处理。它提供了很大的灵活性，
因此开发者能够处理未被便利函数覆盖的不常见用例。

class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=None, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=(), *, group=None, extra_groups=None, user=None, umask=-1, encoding=None, errors=None, text=None, pipesize=-1, process_group=None)

   在一个新的进程中执行子程序。在 POSIX 上，该类会使用类似于
   "os.execvpe()" 的行为来执行子程序。在 Windows 上，该类会使用
   Windows "CreateProcess()" 函数。 "Popen" 的参数如下。

   *args* 应当是一个程序参数的序列或者是一个单独的字符串或 *path-like
   object*。默认情况下，如果 *args* 是序列则要运行的程序为 *args* 中的
   第一项。如果 *args* 是字符串，则其解读依赖于具体平台，如下所述。请
   查看 *shell* 和 *executable* 参数了解其与默认行为的其他差异。除非另
   有说明，否则推荐以序列形式传入 *args*。

   警告:

     为了最大化可靠性，请使用可执行文件的完整限定路径。要在 "PATH" 中
     搜索一个非限定名称，请使用 "shutil.which()"。在所有平台上，传入
     "sys.executable" 是再次启动当前 Python 解释器的推荐方式，并请使用
     "-m" 命令行格式来启动已安装的模块。对 *executable* (或 *args* 的
     第一项) 路径的解析方式依赖于具体平台。对于 POSIX，请参阅
     "os.execvpe()"，并要注意当解析或搜索可执行文件路径时，*cwd* 会覆
     盖当前工作目录而 *env* 可以覆盖 "PATH" 环境变量。对于 Windows，请
     参阅 "lpApplicationName" 的文档以及 "lpCommandLine" 形参 (传给
     WinAPI "CreateProcess")，并要注意当解析或搜索可执行文件路径时如果
     传入 "shell=False"，则 *cwd* 不会覆盖当前工作目录而 *env* 无法覆
     盖 "PATH" 环境变量。使用完整路径可避免所有这些变化情况。

   向外部程序传入序列形式参数的一个例子如下:

      Popen(["/usr/bin/git", "commit", "-m", "Fixes a bug."])

   在 POSIX，如果 *args* 是一个字符串，此字符串被作为将被执行的程序的
   命名或路径解释。但是，只有在不传递任何参数给程序的情况下才能这么做
   。

   备注:

     将 shell 命令拆分为参数序列的方式可能并不很直观，特别是在复杂的情
     况下。 "shlex.split()" 可以演示如何确定 *args* 适当的拆分形式:

        >>> import shlex, subprocess
        >>> command_line = input()
        /bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "echo '$MONEY'"
        >>> args = shlex.split(command_line)
        >>> print(args)
        ['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "echo '$MONEY'"]
        >>> p = subprocess.Popen(args) # Success!

     特别注意，由 shell 中的空格分隔的选项（例如 *-input*）和参数（例
     如 *eggs.txt* ）位于分开的列表元素中，而在需要时使用引号或反斜杠
     转义的参数在 shell（例如包含空格的文件名或上面显示的 *echo* 命令
     ）是单独的列表元素。

   在 Windows，如果 *args* 是一个序列，它将通过一个在 在 Windows 上将
   参数列表转换为一个字符串 描述的方式被转换为一个字符串。这是因为底层
   的 "CreateProcess()" 只处理字符串。

   在 3.6 版本发生变更: 在 POSIX 上如果 *shell* 为 "False" 并且序列包
   含路径类对象则 *args* 形参可以接受一个 *path-like object*.

   在 3.8 版本发生变更: 如果在 Windows 上 *shell* 为 "False" 并且序列
   包含字节串和路径类对象则 *args* 形参可以接受一个 *path-like
   object*.

   参数 *shell* （默认为 "False"）指定是否使用 shell 执行程序。如果
   *shell* 为 "True"，更推荐将 *args* 作为字符串传递而非序列。

   在 POSIX，当 "shell=True"，shell 默认为 "/bin/sh"。如果 *args* 是一
   个字符串，此字符串指定将通过 shell 执行的命令。这意味着字符串的格式
   必须和在命令提示符中所输入的完全相同。这包括，例如，引号和反斜杠转
   义包含空格的文件名。如果 *args* 是一个序列，第一项指定了命令，另外
   的项目将作为传递给 shell（而非命令）的参数对待。也就是说， "Popen"
   等同于:

      Popen(['/bin/sh', '-c', args[0], args[1], ...])

   在 Windows，使用 "shell=True"，环境变量 "COMSPEC" 指定了默认 shell
   。在 Windows 你唯一需要指定 "shell=True" 的情况是你想要执行内置在
   shell 中的命令（例如 **dir** 或者 **copy**）。在运行一个批处理文件
   或者基于控制台的可执行文件时，不需要 "shell=True"。

   备注:

     在使用 "shell=True" 之前，请阅读 Security Considerations 段落。

   *bufsize* 将在 "open()" 函数创建了 stdin/stdout/stderr 管道文件对象
   时作为对应的参数供应：

   * "0" 表示不使用缓冲区（读取与写入是一个系统调用并且可以返回短内容
     ）

   * "1" 表示带有行缓冲（仅在 "text=True" 或 "universal_newlines=True"
     时有用）

   * 任何其他正值表示使用一个约为对应大小的缓冲区

   * 负的 *bufsize* （默认）表示使用系统默认的 io.DEFAULT_BUFFER_SIZE
     。

   在 3.3.1 版本发生变更: *bufsize* 现在默认为 -1 表示启用缓冲以符合大
   多数代码所期望的行为。在 Python 3.2.4 和 3.3.1 之前的版本中它错误地
   将默认值设为 "0" 即无缓冲并且允许短读取。这是无意的失误并且与大多数
   代码所期望的 Python 2 的行为不一致。

   *executable* 参数指定一个要执行的替换程序。这很少需要。当
   "shell=False"， *executable* 替换 *args* 指定运行的程序。但是，原始
   的 *args* 仍然被传递给程序。大多数程序将被 *args* 指定的程序作为命
   令名对待，这可以与实际运行的程序不同。在 POSIX， *args* 名作为实际
   调用程序中可执行文件的显示名称，例如 **ps**。如果 "shell=True"，在
   POSIX， *executable* 参数指定用于替换默认 shell "/bin/sh" 的 shell
   。

   在 3.6 版本发生变更: 在 POSIX 上 *executable* 形参可以接受一个
   *path-like object*。

   在 3.8 版本发生变更: 在 Windows 上 *executable* 形参可以接受一个字
   节串和 *path-like object*。

   在 3.12 版本发生变更: 针对 "shell=True" 改变的 Windows shell 搜索顺
   序。当前目录和 "%PATH%" 会被替换为 "%COMSPEC%" 和
   "%SystemRoot%\\System32\\cmd.exe"。因此，在当前目录中投放一个命名为
   "cmd.exe" 的恶意程序不会再起作用。

   *stdin*, *stdout* 和 *stderr* 分别指定被执行程序的标准输入、标准输
   出和标准错误文件句柄。合法的值包括 "None", "PIPE", "DEVNULL", 现存
   的文件描述符（一个正整数），现存的具有合法文件描述符的 *file
   object*。当使用默认设置 "None" 时，将不会进行任何重定向。 "PIPE" 表
   示应当新建一个连接子进程的管道。 "DEVNULL" 表示将使用特殊文件
   "os.devnull"。此外，*stderr* 还可以为 "STDOUT"，这表示来自子进程的
   stderr 数据应当被捕获到与 *stdout* 相同的文件句柄中。

   如果 *preexec_fn* 被设为一个可调用对象，此对象将在子进程刚创建时被
   调用。（仅 POSIX）

   警告:

     *preexec_fn* 形参在应用程序中存在多线程时是不安全的。子进程在
     exec 被调用之前可能会死锁。

   备注:

     如果你需要为子进程修改环境请使用 *env* 形参而不要在 *preexec_fn*
     中操作。 *start_new_session* 和 *process_group* 形参应当代替使用
     *preexec_fn* 的代码来在子进程中调用 "os.setsid()" 或
     "os.setpgid()".

   在 3.8 版本发生变更: *preexec_fn* 形参在子解释器中已不再受支持。在
   子解释器中使用此形参将引发 "RuntimeError"。 这个新限制可能会影响部
   署在 mod_wsgi, uWSGI 和其他嵌入式环境中的应用。

   如果 *close_fds* 为真值，则除 "0", "1" 和 "2" 之外的所有文件描述符
   都将在子进程执行前被关闭。而当 *close_fds* 为假值时，文件描述符将遵
   循它们的可继承旗标，如 文件描述符的继承 所描述的。

   在 Windows，如果 *close_fds* 为真，则子进程不会继承任何句柄，除非在
   "STARTUPINFO.lpAttributeList" 的 "handle_list" 的键中显式传递，或者
   通过标准句柄重定向传递。

   在 3.2 版本发生变更: *close_fds* 的默认值已经从 "False" 修改为上述
   值。

   在 3.7 版本发生变更: 在 Windows，当重定向标准句柄时 *close_fds* 的
   默认值从 "False" 变为 "True"。现在重定向标准句柄时有可能设置
   *close_fds* 为 "True"。（标准句柄指三个 stdio 的句柄）

   *pass_fds* 是一个可选的在父子进程间保持打开的文件描述符序列。提供任
   何 *pass_fds* 将强制 *close_fds* 为 "True"。（仅 POSIX）

   在 3.2 版本发生变更: 加入了 *pass_fds* 形参。

   如果 *cwd* 不为 "None"，此函数在执行子进程前会将当前工作目录改为
   *cwd*。 *cwd* 可以是一个字符串、字节串或 *路径类对象*。在 POSIX 上
   ，如果可执行文件路径为相对路径则此函数会相对于 *cwd* 来查找
   *executable* (或 *args* 的第一项)。

   在 3.6 版本发生变更: 在 POSIX 上 *cwd* 形参接受一个 *path-like
   object*。

   在 3.7 版本发生变更: 在 Windows 上 *cwd* 形参接受一个 *path-like
   object*。

   在 3.8 版本发生变更: 在 Windows 上 *cwd* 形参接受一个字节串对象。

    如果 *restore_signals* 为 true（默认值），则 Python 设置为 SIG_IGN
   的所有信号将在 exec 之前的子进程中恢复为 SIG_DFL。目前，这包括
   SIGPIPE，SIGXFZ 和 SIGXFSZ 信号。 （仅 POSIX）

   在 3.2 版本发生变更: *restore_signals* 被加入。

   如果 *start_new_session* 为真值则 "setsid()" 系统调用将在执行子进程
   之前在子进程中执行。

   适用范围: POSIX

   在 3.2 版本发生变更: *start_new_session* 被添加。

   如果 *process_group* 为非负整数，则 "setpgid(0, value)" 系统调用将
   在执行子进程之前在子进程中执行。

   适用范围: POSIX

   在 3.11 版本发生变更: 添加了 *process_group*。

   如果 *group* 不为 "None"，则 setregid() 系统调用将在子进程执行之前
   在下级进程中进行。如果所提供的值是一个字符串，将通过
   "grp.getgrnam()" 来查找它并将使用 "gr_gid" 中的值。如果该值是一个整
   数，它将被原样传递。 （POSIX 专属）

   适用范围: POSIX

   Added in version 3.9.

   如果 *extra_groups* 不为 "None"，则 setgroups() 系统调用将在子进程
   执行之前在下级进程中进行。在 *extra_groups* 中提供的字符串将通过
   "grp.getgrnam()" 来查找并将使用 "gr_gid" 中的值。 整数值将被原样传
   递。 （POSIX 专属）

   适用范围: POSIX

   Added in version 3.9.

   如果 *user* 不为 "None"，则 setreuid() 系统调用将在子进程执行之前
   在下级进程中进行。如果所提供的值是一个字符串，将通过
   "pwd.getpwnam()" 来查找它并将使用 "pw_uid" 中的值。如果该值是一个整
   数，它将被原样传递。 （POSIX 专属）

   适用范围: POSIX

   Added in version 3.9.

   如果 *umask* 不为负值，则 umask() 系统调用将在子进程执行之前在下级
   进程中进行。

   适用范围: POSIX

   Added in version 3.9.

   如果 *env* 不为 "None"，则它必须是一个为新进程定义环境变量的映射；
   它们将顶替继承当前环境的默认行为被使用。 这个映射在任何平台上均可以
   是字符串到字符串的映射或者在 POSIX 平台上也可以是字节串到字节串的映
   射，就像是 "os.environ" 或者 "os.environb"。

   备注:

     如果指定，*env* 必须提供待执行程序所需的任何变量。在 Windows 中，
     为了运行一个 side-by-side assembly 指定的 *env* **必须** 包括一个
     有效的 "%SystemRoot%"。

   如果指定了 *encoding* 或 *errors*，或者如果 *text* 为真值，则文件对
   象 *stdin*, *stdout* 和 *stderr* 将使用指定的 *encoding* 和
   *errors* 以文本模式打开，就如上文 常用参数 中所描述的。
   *universal_newlines* 参数等同于 *text* 且是出于下向兼容性考虑而提供
   的。 在默认情况下，文件对象将以二进制模式打开。

   Added in version 3.6: *encoding* 和 *errors* 被添加。

   Added in version 3.7: *text* 作为 *universal_newlines* 的一个更具可
   读性的别名被添加。

   如果给出，*startupinfo* 将是一个 "STARTUPINFO" 对象，它会被传递给下
   层的 "CreateProcess" 函数。

   如果给出，*creationflags* 可以是下列旗标中的一个或多个：

   * "CREATE_NEW_CONSOLE"

   * "CREATE_NEW_PROCESS_GROUP"

   * "ABOVE_NORMAL_PRIORITY_CLASS"

   * "BELOW_NORMAL_PRIORITY_CLASS"

   * "HIGH_PRIORITY_CLASS"

   * "IDLE_PRIORITY_CLASS"

   * "NORMAL_PRIORITY_CLASS"

   * "REALTIME_PRIORITY_CLASS"

   * "CREATE_NO_WINDOW"

   * "DETACHED_PROCESS"

   * "CREATE_DEFAULT_ERROR_MODE"

   * "CREATE_BREAKAWAY_FROM_JOB"

   当 "PIPE" 被用作 *stdin*, *stdout* 或 *stderr* 时 *pipesize* 可被用
   于改变管道的大小。 管道的大小仅会在受支持的平台上被改变（当撰写本文
   档时只有 Linux 支持）。其他平台将忽略此形参。

   在 3.10 版本发生变更: 增加了 *pipesize* 形参。

   Popen 对象支持通过 "with" 语句作为上下文管理器，在退出时关闭文件描
   述符并等待进程:

      with Popen(["ifconfig"], stdout=PIPE) as proc:
          log.write(proc.stdout.read())

   Popen 和此模块中用到它的其他函数会引发一个 审计事件
   "subprocess.Popen"，附带参数 "executable", "args", "cwd" 和 "env"。
   "args" 的值可以是单个字符串或字符串列表，取决于具体的平台。

   在 3.2 版本发生变更: 添加了上下文管理器支持。

   在 3.6 版本发生变更: 现在，如果 Popen 析构时子进程仍然在运行，则析
   构器会发送一个 "ResourceWarning" 警告。

   在 3.8 版本发生变更: 在某些情况下 Popen 可以使用 "os.posix_spawn()"
   以获得更好的性能。在适用于 Linux 的 Windows 子系统和 QEMU 用户模拟
   器上，使用 "os.posix_spawn()" 的 Popen 构造器不再会因找不到程序等错
   误而引发异常，而是子进程失败并返回一个非零的 "returncode"。


异常
----

在子进程中抛出的异常，在新的进程开始执行前，将会被再次在父进程中抛出。

被引发的最一般异常是 "OSError"。例如这会在尝试执行一个不存在的文件时发
生。应用程序应当为 "OSError" 异常做好准备。请注意，如果 "shell=True"，
则 "OSError" 仅会在未找到选定的 shell 本身时被引发。要确定 shell 是否
未找到所请求的应用程序，必须检查来自子进程的返回码或输出。

如果 "Popen" 调用时有无效的参数，则一个 "ValueError" 将被抛出。

"check_call()" 与 "check_output()" 在调用的进程返回非零退出码时将抛出
"CalledProcessError".

所有接受 *timeout* 形参的函数与方法，例如 "run()" 和
"Popen.communicate()" 将会在进程退出前超时到期时引发 "TimeoutExpired"
。

此模块中定义的异常都继承自 "SubprocessError"。

Added in version 3.3: 基类 "SubprocessError" 被添加。


安全考量
========

不同于某些其他的 popen 函数，这个库将不会隐式地选择调用系统 shell。这
意味着所有字符，包括 shell 元字符都可以被安全地传递给子进程。 如果
shell 是通过 "shell=True" 被显式地唤起的，则应用程序要负责确保所有空白
符和元字符被适当地转义以避免 shell 注入 安全漏洞。在 某些平台 上，可以
使用 "shlex.quote()" 来执行这种转义。

在 Windows 上，批处理文件 ("*.bat" 或 "*.cmd") 可以在系统 shell 中通过
操作系统调用来启动而忽略传给该库的参数。这可能导致根据 shell 规则来解
析参数，而没有任何 Python 添加的转义。 如果你想要附带来自不受信任源的
参数启动批处理文件，请考虑传入 "shell=True" 以允许 Python 转义特殊字符
。请参阅 gh-114539 了解相关讨论。


Popen 对象
==========

"Popen" 类的实例拥有以下方法：

Popen.poll()

   检查子进程是否已被终止。设置并返回 "returncode" 属性。否则返回
   "None"。

Popen.wait(timeout=None)

   等待子进程被终止。设置并返回 "returncode" 属性。

   如果进程在 *timeout* 秒后未中断，抛出一个 "TimeoutExpired" 异常，可
   以安全地捕获此异常并重新等待。

   备注:

     当 "stdout=PIPE" 或者 "stderr=PIPE" 并且子进程产生了足以阻塞 OS
     管道缓冲区接收更多数据的输出到管道时，将会发生死锁。当使用管道时
     用 "Popen.communicate()" 来规避它。

   备注:

     当 "timeout" 形参不为 "None" 时，该函数（在 POSIX 上）将使用一个
     忙循环（非阻塞调用及短睡眠）来实现。使用 "asyncio" 模块进行异步等
     待：参见 "asyncio.create_subprocess_exec"。

   在 3.3 版本发生变更: *timeout* 被添加

Popen.communicate(input=None, timeout=None)

   与进程交互：将数据发送到 stdin。从 stdout 和 stderr 读取数据，直到
   抵达文件结尾。等待进程终止并设置 "returncode" 属性。可选的 *input*
   参数应为要发送到下级进程的数据，或者如果没有要发送到下级进程的数据
   则为 "None"。如果流是以文本模式打开的，则 *input* 必须为字符串。 在
   其他情况下，它必须为字节串。

   "communicate()" 返回一个 "(stdout_data, stderr_data)" 元组。如果文
   件以文本模式打开则为字符串；否则字节。

   注意如果你想要向进程的 stdin 传输数据，你需要通过 "stdin=PIPE" 创建
   此 Popen 对象。类似的，要从结果元组获取任何非 "None" 值，你同样需要
   设置 "stdout=PIPE" 或者 "stderr=PIPE"。

   如果进程在 *timeout* 秒后仍未终结，将会引发 "TimeoutExpired" 异常。
   捕获此异常并重试通信将不会丢失任何输出。将 *input* 提供给后续的已超
   时 "communicate()" 调用是未定义的行为并可能在未来导致错误。

   如果超时到期，子进程不会被杀死，所以为了正确清理一个行为良好的应用
   程序应该杀死子进程并完成通讯。

      proc = subprocess.Popen(...)
      try:
          outs, errs = proc.communicate(timeout=15)
      except TimeoutExpired:
          proc.kill()
          outs, errs = proc.communicate()

   在对 "communicate()" 的调用引发 "TimeoutExpired" 之后，不要调用
   "wait()"。请用一个额外的 "communicate()" 来结束处理管道并填充
   "returncode" 属性。

   备注:

     内存里数据读取是缓冲的，所以如果数据尺寸过大或无限，不要使用此方
     法。

   在 3.3 版本发生变更: *timeout* 被添加

Popen.send_signal(signal)

   将信号 *signal* 发送给子进程。

   如果进程已完成则不做任何操作。

   备注:

     在 Windows 上，SIGTERM 是 "terminate()" 的别名。CTRL_C_EVENT 和
     CTRL_BREAK_EVENT 可被发送给以包括 "CREATE_NEW_PROCESS_GROUP" 的
     *creationflags* 形参来启动的进程。

Popen.terminate()

   停止子进程。在 POSIX 操作系统上此方法会发送 "SIGTERM" 给子进程。在
   Windows 上则会调用 Win32 API 函数 "TerminateProcess()" 来停止子进程
   。

Popen.kill()

   杀死子进程。在 POSIX 操作系统上，此函数会发送 SIGKILL 给子进程。在
   Windows 上 "kill()" 则是 "terminate()" 的别名。

下列属性也会通过类来设置以供你访问。将它们重赋新值是不受支持的：

Popen.args

   *args* 参数传递给 "Popen" -- 一个程序参数的序列或者一个简单字符串。

   Added in version 3.3.

Popen.stdin

   如果 *stdin* 参数为 "PIPE"，此属性是一个类似 "open()" 所返回对象的
   可写流对象。如果指定了 *encoding* 或 *errors* 参数或者 *text* 或
   *universal_newlines* 参数为 "True"，则这个流将是一个文本流，否则将
   是一个字节流。如果 *stdin* 参数不为 "PIPE"，则此属性将为 "None".

Popen.stdout

   如果 *stdout* 参数为 "PIPE"，此属性是一个类似 "open()" 所返回对象的
   可读流对象。 从流中读取将会提供来自子进程的输出。如果 *encoding* 或
   *errors* 参数被指定或者 *text* 或 *universal_newlines* 参数为
   "True"，则这个流将是一个文本流，否则将是一个字节流。如果 *stdout*
   参数不为 "PIPE"，则此属性将为 "None"。

Popen.stderr

   如果 *stderr* 参数为 "PIPE"，此属性是一个类似 "open()" 所返回对象的
   可读流对象。 从流中读取将会提供来自子进程的错误输出。如果
   *encoding* 或 *errors* 参数被指定或者 *text* 或
   *universal_newlines* 参数为 "True"，则这个流将是一个文本流，否则将
   是一个字节流。如果 *stderr* 参数不为 "PIPE"，则此属性将为 "None"。

警告:

  使用 "communicate()" 而非 ".stdin.write"， ".stdout.read" 或者
  ".stderr.read" 来避免由于任意其他 OS 管道缓冲区被子进程填满阻塞而导
  致的死锁。

Popen.pid

   子进程的进程号。

   注意如果你设置了 *shell* 参数为 "True"，则这是生成的子 shell 的进程
   号。

Popen.returncode

   子进程的返回码。初始为 "None"，"returncode" 是通过在检测到进程终结
   时调用 "poll()", "wait()" 或 "communicate()" 等方法来设置的。

   "None" 值表示在最近一次方法调用时进程尚未终结

   一个负值 "-N" 表示子进程被信号 "N" 中断 (仅 POSIX).

   When "shell=True", the return code reflects the exit status of the
   shell itself (e.g. "/bin/sh"), which may map signals to codes such
   as "128+N". See the documentation of the shell (for example, the
   Bash manual's Exit Status) for details.


Windows Popen 助手
==================

"STARTUPINFO" 类和以下常数仅在 Windows 有效。

class subprocess.STARTUPINFO(*, dwFlags=0, hStdInput=None, hStdOutput=None, hStdError=None, wShowWindow=0, lpAttributeList=None)

   在 "Popen" 创建时部分支持 Windows 的 STARTUPINFO 结构。接下来的属性
   仅能通过关键词参数设置。

   在 3.7 版本发生变更: 仅关键词参数支持被加入。

   dwFlags

      一个位字段，用于确定进程在创建窗口时是否使用某些 "STARTUPINFO"
      属性。

         si = subprocess.STARTUPINFO()
         si.dwFlags = subprocess.STARTF_USESTDHANDLES | subprocess.STARTF_USESHOWWINDOW

   hStdInput

      如果 "dwFlags" 被指定为 "STARTF_USESTDHANDLES"，则此属性是进程的
      标准输入句柄，如果 "STARTF_USESTDHANDLES" 未指定，则默认的标准输
      入是键盘缓冲区。

   hStdOutput

      如果 "dwFlags" 被指定为 "STARTF_USESTDHANDLES"，则此属性是进程的
      标准输出句柄。除此之外，此属性将被忽略并且默认标准输出是控制台窗
      口缓冲区。

   hStdError

      如果 "dwFlags" 被指定为 "STARTF_USESTDHANDLES"，则此属性是进程的
      标准错误句柄。除此之外，此属性将被忽略并且默认标准错误为控制台窗
      口的缓冲区。

   wShowWindow

      如果 "dwFlags" 指定了 "STARTF_USESHOWWINDOW"，此属性可为能被指定
      为 函数 ShowWindow 的 nCmdShow 的形参的任意值，除了
      "SW_SHOWDEFAULT"。如此之外，此属性被忽略。

      "SW_HIDE" 被提供给此属性。它在 "Popen" 由 "shell=True" 调用时使
      用。

   lpAttributeList

      "STARTUPINFOEX" 给出的用于进程创建的额外属性字典，参阅
      UpdateProcThreadAttribute.

      支持的属性：

      **handle_list**
         将被继承的句柄的序列。如果非空， *close_fds* 必须为 true。

         当传递给 "Popen" 构造函数时，这些句柄必须暂时地能被
         "os.set_handle_inheritable()" 继承，否则 "OSError" 将以
         Windows error "ERROR_INVALID_PARAMETER" (87) 抛出。

         警告:

           在多线程进程中，请谨慎使用，以便在将此功能与对继承所有句柄
           的其他进程创建函数——例如 "os.system()" 的并发调用——相结合时
           ，避免泄漏标记为可继承的句柄。这也应用于临时性创建可继承句
           柄的标准句柄重定向。

      Added in version 3.7.


Windows 常数
------------

"subprocess" 模块对外暴露了下列常量。

subprocess.STD_INPUT_HANDLE

   标准输入设备，这是控制台输入缓冲区 "CONIN$"。

subprocess.STD_OUTPUT_HANDLE

   标准输出设备。最初，这是活动控制台屏幕缓冲区 "CONOUT$"。

subprocess.STD_ERROR_HANDLE

   标准错误设备。最初，这是活动控制台屏幕缓冲区 "CONOUT$"。

subprocess.SW_HIDE

   隐藏窗口。另一个窗口将被激活。

subprocess.STARTF_USESTDHANDLES

   指明 "STARTUPINFO.hStdInput", "STARTUPINFO.hStdOutput" 和
   "STARTUPINFO.hStdError" 属性包含额外的信息。

subprocess.STARTF_USESHOWWINDOW

   指明 "STARTUPINFO.wShowWindow" 属性包含额外的信息。

subprocess.STARTF_FORCEONFEEDBACK

   "STARTUPINFO.dwFlags" 形参指明在进程启动时将显示一个 *正在后台操作*
   鼠标提示。这是 GUI 进程的默认行为。

   Added in version 3.13.

subprocess.STARTF_FORCEOFFFEEDBACK

   "STARTUPINFO.dwFlags" 形参指明在启动进程时鼠标提示将不会改变。

   Added in version 3.13.

subprocess.CREATE_NEW_CONSOLE

   新的进程将有新的控制台，而不是继承父进程的（默认）控制台。

subprocess.CREATE_NEW_PROCESS_GROUP

   用于指明将创建一个新的进程组的 "Popen" "creationflags" 形参。这个旗
   标对于在子进程上使用 "os.kill()" 来说是必须的。

   如果指定了 "CREATE_NEW_CONSOLE" 则这个旗标会被忽略。

subprocess.ABOVE_NORMAL_PRIORITY_CLASS

   用于指明一个新进程将具有高于平均的优先级的 "Popen" "creationflags"
   形参。

   Added in version 3.7.

subprocess.BELOW_NORMAL_PRIORITY_CLASS

   用于指明一个新进程将具有低于平均的优先级的 "Popen" "creationflags"
   形参。

   Added in version 3.7.

subprocess.HIGH_PRIORITY_CLASS

   用于指明一个新进程将具有高优先级的 "Popen" "creationflags" 形参。

   Added in version 3.7.

subprocess.IDLE_PRIORITY_CLASS

   用于指明一个新进程将具有空闲（最低）优先级的 "Popen"
   "creationflags" 形参。

   Added in version 3.7.

subprocess.NORMAL_PRIORITY_CLASS

   用于指明一个新进程将具有正常（默认）优先级的 "Popen"
   "creationflags" 形参。

   Added in version 3.7.

subprocess.REALTIME_PRIORITY_CLASS

   用于指明一个新进程将具有实时优先级的 "Popen" "creationflags" 形参。
   你应当几乎永远不使用 REALTIME_PRIORITY_CLASS，因为这会中断管理鼠标
   输入、键盘输入以及后台磁盘刷新的系统线程。 这个类只适用于直接与硬件
   “对话”，或者执行短暂任务具有受限中断的应用。

   Added in version 3.7.

subprocess.CREATE_NO_WINDOW

   指明一个新进程将不会创建窗口的 "Popen" "creationflags" 形参。

   Added in version 3.7.

subprocess.DETACHED_PROCESS

   指明一个新进程将不会继承其父控制台的 "Popen" "creationflags" 形参。
   这个值不能与 CREATE_NEW_CONSOLE 一同使用。

   Added in version 3.7.

subprocess.CREATE_DEFAULT_ERROR_MODE

   指明一个新进程不会继承调用方进程的错误模式的 "Popen"
   "creationflags" 形参。新进程会转为采用默认的错误模式。 这个特性特别
   适用于运行时禁用硬错误的多线程 shell 应用。

   Added in version 3.7.

subprocess.CREATE_BREAKAWAY_FROM_JOB

   指明一个新进程不会关联到任务的 "Popen" "creationflags" 形参。

   Added in version 3.7.


较旧的高阶 API
==============

在 Python 3.5 之前，这三个函数组成了 subprocess 的高阶 API。现在你可以
在许多情况下使用 "run()"，但有大量现在代码仍会调用这些函数。

subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, **other_popen_kwargs)

   运行由 *args* 所描述的命令。等待命令完成，然后返回 "returncode" 属
   性。

   需要捕获 stdout 或 stderr 的代码应当改用 "run()":

      run(...).returncode

   要屏蔽 stdout 或 stderr，可提供 "DEVNULL" 这个值。

   上面显示的参数只是常见的一些。完整的函数签名与 "Popen" 构造器的相同
   —— 此函数会将所提供的 *timeout* 之外的全部参数直接传递给目标接口。

   备注:

     请不要在此函数中使用 "stdout=PIPE" 或 "stderr=PIPE"。如果子进程向
     管道生成了足以填满 OS 管道缓冲区的输出而管道还未被读取时它将会阻
     塞。

   在 3.3 版本发生变更: *timeout* 被添加

   在 3.12 版本发生变更: 针对 "shell=True" 改变的 Windows shell 搜索顺
   序。当前目录和 "%PATH%" 会被替换为 "%COMSPEC%" 和
   "%SystemRoot%\\System32\\cmd.exe"。因此，在当前目录中投放一个命名为
   "cmd.exe" 的恶意程序不会再起作用。

subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, **other_popen_kwargs)

   附带参数运行命令。等待命令完成。如果返回码为零则正常返回，否则引发
   "CalledProcessError"。 "CalledProcessError" 对象将在 "returncode"
   属性中保存返回码。如果 "check_call()" 无法开始进程则它将传播已被引
   发的异常。

   需要捕获 stdout 或 stderr 的代码应当改用 "run()":

      run(..., check=True)

   要屏蔽 stdout 或 stderr，可提供 "DEVNULL" 这个值。

   上面显示的参数只是常见的一些。完整的函数签名与 "Popen" 构造器的相同
   —— 此函数会将所提供的 *timeout* 之外的全部参数直接传递给目标接口。

   备注:

     请不要在此函数中使用 "stdout=PIPE" 或 "stderr=PIPE"。如果子进程向
     管道生成了足以填满 OS 管道缓冲区的输出而管道还未被读取时它将会阻
     塞。

   在 3.3 版本发生变更: *timeout* 被添加

   在 3.12 版本发生变更: 针对 "shell=True" 改变的 Windows shell 搜索顺
   序。当前目录和 "%PATH%" 会被替换为 "%COMSPEC%" 和
   "%SystemRoot%\\System32\\cmd.exe"。因此，在当前目录中投放一个命名为
   "cmd.exe" 的恶意程序不会再起作用。

subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, cwd=None, encoding=None, errors=None, universal_newlines=None, timeout=None, text=None, **other_popen_kwargs)

   附带参数运行命令并返回其输出。

   如果返回码非零则会引发 "CalledProcessError"。 "CalledProcessError"
   对象将在 "returncode" 属性中保存返回码并在 "output" 属性中保存所有
   输出。

   这相当于：

      run(..., check=True, stdout=PIPE).stdout

   上面显示的参数只是常见的一些。完整的函数签名与 "run()" 的大致相同
   —— 大部分参数会通过该接口直接传递。存在一个与 "run()" 行为不同的
   API 差异：传递 "input=None" 的行为将与 "input=b''" (或 "input=''"，
   具体取决于其他参数) 一样而不是使用父对象的标准输入文件处理。

   默认情况下，此函数将把数据返回为已编码的字节串。输出数据的实际编码
   格式将取决于唤起的命令，因此解码为文本的操作往往需要在应用程序层级
   上进行处理。

   此行为可以通过设置 *text*, *encoding*, *errors* 或将
   *universal_newlines* 设为 "True" 来重载，具体描述见 常用参数 和
   "run()"。

   要在结果中同时捕获标准错误，请使用 "stderr=subprocess.STDOUT":

      >>> subprocess.check_output(
      ...     "ls non_existent_file; exit 0",
      ...     stderr=subprocess.STDOUT,
      ...     shell=True)
      'ls: non_existent_file: No such file or directory\n'

   Added in version 3.1.

   在 3.3 版本发生变更: *timeout* 被添加

   在 3.4 版本发生变更: 增加了对 *input* 关键字参数的支持。

   在 3.6 版本发生变更: 增加了 *encoding* 和 *errors*。详情参见
   "run()"。

   Added in version 3.7: *text* 作为 *universal_newlines* 的一个更具可
   读性的别名被添加。

   在 3.12 版本发生变更: 针对 "shell=True" 改变的 Windows shell 搜索顺
   序。当前目录和 "%PATH%" 会被替换为 "%COMSPEC%" 和
   "%SystemRoot%\\System32\\cmd.exe"。因此，在当前目录中投放一个命名为
   "cmd.exe" 的恶意程序不会再起作用。


使用 "subprocess" 模块替代旧有函数
==================================

在这一节中，"a 改为 b" 意味着 b 可以被用作 a 的替代。

备注:

  在这一节中的所有 "a" 函数会在找不到被执行的程序时（差不多）静默地失
  败；"b" 替代函数则会改为引发 "OSError"。此外，在使用
  "check_output()" 时如果替代函数所请求的操作产生了非零返回值则将失败
  并引发 "CalledProcessError"。操作的输出仍能以所引发异常的 "output"
  属性的方式被访问。

In the following examples, we assume that the relevant functions have
already been imported from the "subprocess" module.


替代 **/bin/sh** shell 命令替换
-------------------------------

   output=$(mycmd myarg)

改为:

   output = check_output(["mycmd", "myarg"])


替代 shell 管道
---------------

   output=$(dmesg | grep hda)

改为:

   p1 = Popen(["dmesg"], stdout=PIPE)
   p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
   p1.stdout.close()  # 允许 p1 在 p2 退出时接收 SIGPIPE。
   output = p2.communicate()[0]

启动 p2 之后再执行 "p1.stdout.close()" 调用很重要，这是为了让 p1 能在
p2 先于 p1 退出时接收到 SIGPIPE。

另外，对于受信任的输入，shell 本身的管道支持仍然可被直接使用：

   output=$(dmesg | grep hda)

改为:

   output = check_output("dmesg | grep hda", shell=True)


替代 "os.system()"
------------------

   sts = os.system("mycmd" + " myarg")
   # 变为
   retcode = call("mycmd" + " myarg", shell=True)

注释：

* 通过 shell 来调用程序通常是不必要的。

* "call()" 返回值的编码方式与 "os.system()" 的不同。

* The "os.system()" function ignores SIGINT and SIGQUIT signals while
  the command is running, but the caller must do this separately when
  using the "subprocess" module.

一个更现实的例子如下所示:

   try:
       retcode = call("mycmd" + " myarg", shell=True)
       if retcode < 0:
           print("Child was terminated by signal", -retcode, file=sys.stderr)
       else:
           print("Child returned", retcode, file=sys.stderr)
   except OSError as e:
       print("Execution failed:", e, file=sys.stderr)


替代 "os.spawn" 函数族
----------------------

P_NOWAIT 示例:

   pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg")
   ==>
   pid = Popen(["/bin/mycmd", "myarg"]).pid

P_WAIT 示例:

   retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd", "mycmd", "myarg")
   ==>
   retcode = call(["/bin/mycmd", "myarg"])

Vector 示例:

   os.spawnvp(os.P_NOWAIT, path, args)
   ==>
   Popen([path] + args[1:])

Environment 示例:

   os.spawnlpe(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg", env)
   ==>
   Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"})


替代 "os.popen()"
-----------------

返回码以如下方式处理转写:

   pipe = os.popen(cmd, 'w')
   ...
   rc = pipe.close()
   if rc is not None and rc >> 8:
       print("There were some errors")
   ==>
   process = Popen(cmd, stdin=PIPE)
   ...
   process.stdin.close()
   if process.wait() != 0:
       print("There were some errors")


旧式的 Shell 发起函数
=====================

此模块还提供了以下来自 2.x "commands" 模块的旧版函数。这些操作会隐式地
唤起系统 shell 并且上文所描述的有关安全与异常处理一致性保证都不适用于
这些函数。

subprocess.getstatusoutput(cmd, *, encoding=None, errors=None)

   返回在 shell 中执行 *cmd* 产生的 "(exitcode, output)"。

   在 shell 中 附带 "check_output()" 来执行字符串 *cmd* 并返回一个 2
   元组 "(exitcode, output)"。 *encoding* 和 *errors* 将被用于对输出进
   行解码；请参阅 常用参数 中的说明来了解详情。

   末尾的一个换行符会从输出中被去除。命令的退出码可被解读为子进程的返
   回码。例如:

      >>> subprocess.getstatusoutput('ls /bin/ls')
      (0, '/bin/ls')
      >>> subprocess.getstatusoutput('cat /bin/junk')
      (1, 'cat: /bin/junk: No such file or directory')
      >>> subprocess.getstatusoutput('/bin/junk')
      (127, 'sh: /bin/junk: not found')
      >>> subprocess.getstatusoutput('/bin/kill $$')
      (-15, '')

   适用范围: Unix, Windows.

   在 3.3.4 版本发生变更: 添加了 Windows 支持。此函数现在返回
   (exitcode, output) 而不是像 Python 3.3.3 及更早的版本那样返回
   (status, output)。 exitcode 的值与 "returncode" 相同。

   在 3.11 版本发生变更: 增加了 *encoding* 和 *errors* 形参。

subprocess.getoutput(cmd, *, encoding=None, errors=None)

   返回在 shell 中执行 *cmd* 产生的输出（stdout 和 stderr）。

   类似于 "getstatusoutput()"，但退出码会被忽略并且返回值为包含命令输
   出的字符串。例如:

      >>> subprocess.getoutput('ls /bin/ls')
      '/bin/ls'

   适用范围: Unix, Windows.

   在 3.3.4 版本发生变更: 添加了 Windows 支持

   在 3.11 版本发生变更: 增加了 *encoding* 和 *errors* 形参。


备注
====


超时行为
--------

当在 "run()"、"Popen.wait()" 或 "Popen.communicate()" 等函数中使用
"timeout" 形参时，用户应该注意以下行为：

1. **进程创建延迟**：在许多平台 API 上，初始进程创建本身不能被中断。这
   意味着，即使指定了超时，也不能保证在创建进程之前看到超时异常，无论
   创建进程花了多长时间。

2. **非常小的超时值**: 设置非常小的超时值（比如几毫秒）可能会导致几乎
   立即出现 "TimeoutExpired" 异常，因为进程创建和系统调度本身就需要时
   间。


在 Windows 上将参数列表转换为一个字符串
---------------------------------------

在 Windows 上，*args* 序列会被转换为可使用以下规则来解析的字符串（对应
于 MS C 运行时所使用的规则）:

1. 参数以空白符分隔，即空格符或制表符。

2. 用双引号标示的字符串会被解读为单个参数，而不再考虑其中的空白符。一
   个参数可以嵌套用引号标示的字符串。

3. 带有一个反斜杠前缀的双引号会被解读为双引号字面值。

4. 反斜杠会按字面值解读，除非它是作为双引号的前缀。

5. 如果反斜杠被作为双引号的前缀，则每个反斜杠对会被解读为一个反斜杠字
   面值。如果反斜杠数量为奇数，则最后一个反斜杠会如规则 3 所描述的那样
   转义下一个双引号。

参见:

  "shlex"
     此模块提供了用于解析和转义命令行的函数。


禁用 "posix_spawn()"
--------------------

On Linux, "subprocess" defaults to using the "vfork()" system call
internally when it is safe to do so rather than "fork()". This greatly
improves performance.

   subprocess._USE_POSIX_SPAWN = False  # 参见 CPython 程序问题 gh-NNNNNN。

在任何 Python 版本上将其设置为 false 都是安全的。它对不受支持的旧版本
或新版本没有影响。不要假设该属性可以读取。除了名称之外，true 值并不表
示将使用相应的函数，只是表示可能会使用。

当你不得不使用这些私有属性并遇到问题时请随时提交问题并附带你所看到的问
题的重现方式。请从你代码中的某条注释链接到该问题。

Added in version 3.8: "_USE_POSIX_SPAWN"
