Julio Cesar Asked: 2020-06-18 19:59:31 +0800 CST 2020-06-18 19:59:31 +0800 CST 2020-06-18 19:59:31 +0800 CST subprocess.run 和 subprocess.Popen 之间的区别 772 我有一个关于图书馆的问题subprocess: subprocess.run()使用andPopen()和在什么情况下应该分别使用有什么区别? python 1 Answers Voted Best Answer FJSevilla 2020-06-19T06:33:38+08:002020-06-19T06:33:38+08:00 该模块的核心subprocess是subprocess.Popen,就其本身而言,它subprocess.run是在 Python 3.5 中添加的,基本上是一个包装器subprocess.Popen,它的创建是为了集成和统一各种旧功能,例如subprocess.call. 它基本上允许您在线程上运行命令并等待它完成。 关键字是“等待”,它run 阻塞主进程,直到子进程中执行的命令完成,同时subprocess.Popen您可以继续在父进程中并行执行操作,随时调用以subprocess.communicate从线程传递或接收数据. 如前所述,subprocess.run它只是让它更易于使用,在它下面调用subprocess.Popen和使用subprocess.comunicate. 实际上,所有参数都直接传递给Popen减三构造函数: timeout:如果进程在它之前没有返回,则将其传递给Popen.communicate生成异常。TimeoutExpired但是,与Popen.comunicateraw 发生的情况不同,在抛出异常之前发送指令以杀死子进程并等待。 input: 也传递给Popen.communicate. 需要注意的是,当内部使用此参数时,Popen 将 stdin 与管道 ( stdin = subprocess.PIPE) 相关联,因此不应与参数一起使用stdin。 check:如果进程以非零退出码退出,则会抛出异常CalledProcessError。 另一方面,subproccess.run 它返回一个subprocess.CompletedProcess表示终止进程结果的对象: subprocess.CompletedProcess.args: 是用于启动进程的参数,与传递给 的参数的对象直接args相关subprocess.run。 subprocess.CompletedProcess.returncode: 只是进程的退出状态。通常 0 表示进程已正确执行,尽管从逻辑上讲它是由进程本身定义的。 subprocess.CompletedProcess.stdout: 捕获线程的标准输出或者None如果它没有被捕获。str如果传递True给 的参数universal_newlines=True,则它是字节字符串或文本字符串 ( ) subprocess.run。为了捕获输出,有必要通过调用subprocess.run通过管道重定向它stdout=subperocess.PIPE subprocess.CompletedProcess.stderr: 和前面的属性完全一样,只是针对stderr. subprocess.CompletedProcess.check_returncode(): 就像在 的构造函数中定义check的一样,如果线程的返回码不为零,则调用此方法时会引发异常。Truesubprocess.runCalledProcessError 至此,您提出的关于何时使用其中一个的第二个问题已经得到解答。您要问自己的是,在父进程中继续执行之前,我是否要等待命令执行并完成?. 如果是这样,请使用subprocess.run. 您显然可以使用subprocess.Popen+实现相同的目的comunicate(),但它需要更多的代码和工作(因此是 的基本原理run)。 对于一个非常简化的示例,假设我们在 *nix 系统上有以下 Python 脚本,我们将作为线程运行: import select import sys import time for i in range(10): time.sleep(1) if select.select([sys.stdin], [], [], 0.0)[0]: if sys.stdin.read() == "salir": break print(f"Se ha esperado {i} segundos") 例如,它什么也不做,只需要大约 10 秒即可完成该过程,但如果我们通过标准输入“退出”它,我们可以随时停止它。 如果我们通过subprocess.run启动该进程,我们的父进程将被阻塞 10 秒,子进程无需多言即可返回: import subprocess process = subprocess.run(args=["python", "dropdownlist.py"], stdout=subprocess.PIPE, stdin=subprocess.PIPE, encoding='utf8' ) print(process.stdout) 等了 10 秒 一旦线程启动,我们的主进程就会阻塞,并且仅 print(process.stdout)在线程终止时继续(执行)。 相反,subprocess.Popen我们可以在进程运行时做其他事情,并最终在某个时候与它通信以停止它: import subprocess import time process = subprocess.Popen(args=["python", "dropdownlist.py"], stdout=subprocess.PIPE, stdin=subprocess.PIPE, encoding='utf8' ) time.sleep(5) # hacemos cualquier cosa mientra tanto out, _ = process.communicate("salir") print(out) 等待 5 秒 想象一下,您有一个 CLI 程序,它播放音频文件,在播放的同时,它通过标准输出返回某些信息,例如进度,还允许您发送暂停、恢复等命令。如果你想从 Python 脚本运行这样的程序,你可以考虑两种可能性。如果你只想从头到尾播放一个文件,同时你的 Python 脚本只是等待而不做任何事情,那subprocess.run将是你最简单的选择。如果您希望能够在使用播放器发送的信息时停止、恢复等播放subprocess.Popen+ comunicate(发送命令并接收播放器通过标准输出发送的信息)是正确的选择。 遵循相同的逻辑,如果您想发出多个旨在并行运行的线程命令,则应该使用它,subprocess.Popen因为它会subprocess.run串行执行它们。
该模块的核心
subprocess
是subprocess.Popen
,就其本身而言,它subprocess.run
是在 Python 3.5 中添加的,基本上是一个包装器subprocess.Popen
,它的创建是为了集成和统一各种旧功能,例如subprocess.call
. 它基本上允许您在线程上运行命令并等待它完成。关键字是“等待”,它
run
阻塞主进程,直到子进程中执行的命令完成,同时subprocess.Popen
您可以继续在父进程中并行执行操作,随时调用以subprocess.communicate
从线程传递或接收数据.如前所述,
subprocess.run
它只是让它更易于使用,在它下面调用subprocess.Popen
和使用subprocess.comunicate
. 实际上,所有参数都直接传递给Popen
减三构造函数:timeout
:如果进程在它之前没有返回,则将其传递给Popen.communicate
生成异常。TimeoutExpired
但是,与Popen.comunicate
raw 发生的情况不同,在抛出异常之前发送指令以杀死子进程并等待。input
: 也传递给Popen.communicate
. 需要注意的是,当内部使用此参数时,Popen 将 stdin 与管道 (stdin = subprocess.PIPE
) 相关联,因此不应与参数一起使用stdin
。check
:如果进程以非零退出码退出,则会抛出异常CalledProcessError
。另一方面,
subproccess.run
它返回一个subprocess.CompletedProcess
表示终止进程结果的对象:subprocess.CompletedProcess.args
: 是用于启动进程的参数,与传递给 的参数的对象直接args
相关subprocess.run
。subprocess.CompletedProcess.returncode
: 只是进程的退出状态。通常 0 表示进程已正确执行,尽管从逻辑上讲它是由进程本身定义的。subprocess.CompletedProcess.stdout
: 捕获线程的标准输出或者None
如果它没有被捕获。str
如果传递True
给 的参数universal_newlines=True
,则它是字节字符串或文本字符串 ( )subprocess.run
。为了捕获输出,有必要通过调用subprocess.run
通过管道重定向它stdout=subperocess.PIPE
subprocess.CompletedProcess.stderr
: 和前面的属性完全一样,只是针对stderr
.subprocess.CompletedProcess.check_returncode()
: 就像在 的构造函数中定义check
的一样,如果线程的返回码不为零,则调用此方法时会引发异常。True
subprocess.run
CalledProcessError
至此,您提出的关于何时使用其中一个的第二个问题已经得到解答。您要问自己的是,在父进程中继续执行之前,我是否要等待命令执行并完成?. 如果是这样,请使用
subprocess.run
. 您显然可以使用subprocess.Popen
+实现相同的目的comunicate()
,但它需要更多的代码和工作(因此是 的基本原理run
)。对于一个非常简化的示例,假设我们在 *nix 系统上有以下 Python 脚本,我们将作为线程运行:
例如,它什么也不做,只需要大约 10 秒即可完成该过程,但如果我们通过标准输入“退出”它,我们可以随时停止它。
如果我们通过subprocess.run启动该进程,我们的父进程将被阻塞 10 秒,子进程无需多言即可返回:
一旦线程启动,我们的主进程就会阻塞,并且仅
print(process.stdout)
在线程终止时继续(执行)。相反,
subprocess.Popen
我们可以在进程运行时做其他事情,并最终在某个时候与它通信以停止它:想象一下,您有一个 CLI 程序,它播放音频文件,在播放的同时,它通过标准输出返回某些信息,例如进度,还允许您发送暂停、恢复等命令。如果你想从 Python 脚本运行这样的程序,你可以考虑两种可能性。如果你只想从头到尾播放一个文件,同时你的 Python 脚本只是等待而不做任何事情,那
subprocess.run
将是你最简单的选择。如果您希望能够在使用播放器发送的信息时停止、恢复等播放subprocess.Popen
+comunicate
(发送命令并接收播放器通过标准输出发送的信息)是正确的选择。遵循相同的逻辑,如果您想发出多个旨在并行运行的线程命令,则应该使用它,
subprocess.Popen
因为它会subprocess.run
串行执行它们。