subprocess 模块,子进程管理(Subprocess management),用于生成新进程,连接到它们的输入/输出/错误管道,并得到它们的返回代码. 其意在取代旧的模块,如 os.system
和 os.spawn*
.
通用场景,推荐采用 subprocess.run()
函数来调用子进程.
更高级应用场景,推荐采用 subprocess.Popen
接口.
中文文档:https://docs.python.org/zh-cn/3/library/subprocess.html#
1. subprocess.run
1.1. 定义
函数定义如:
subprocess.run(args, *,
stdin=None,
input=None,
stdout=None,
stderr=None,
capture_output=False,
shell=False, #若True,则采用操作系统的 shell 执行命令
cwd=None,
timeout=None, #超时时间
check=False,
encoding=None, #编码格式
errors=None,
text=None,
env=None,
universal_newlines=None,
**other_popen_kwargs)
函数功能为,通过参数 args
运行命令,当执行完毕后,返回一个 CompletedProcess
实例.
[1] - capture_output=True
则捕获 stdout
和 stderr
1.2. 示例
run 方法和直接用 Popen 差不多,实现一样,其实际上也是调用 Popen.
import subprocess
#执行 ls -lh /home
subprocess.run(["ls", "-lh", "/home"])
#输出:
# CompletedProcess(args=['ls', '-lh', '/home'], returncode=0)
subprocess.run(["ls", "-l", "/dev/null"], capture_output=True)
再如,
import subprocess
def cmd(command):
ret = subprocess.run(command,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
encoding="utf-8",
timeout=1)
if ret.returncode == 0:
print("success:",ret)
else:
print("error:",ret)
#
cmd(["dir","/home"]) #序列参数
cmd(["nvidia-smi"])
cmd("exit 1") #字符串参数
2. subprocess.CompletedProcess
CompletedProcess
是 subprocess.run()
的返回值,表示一个进程已经完成.
其包含:
[1] - args
: 启动进程的参数,可以是 list 或 str.
[2] - returncode
: 子进程的退出状态. 一般情况下,退出状态为 0 表示成功运行; 退出状态为-N
表示子进程被信号 N
终止.
[3] - stdout
: 捕获子进程的 stdout. 一般为字节或字符串;如值为 None
则表示没有捕获到 stdout.
[4] - stderr
: 捕获子进程的 stderr.
[5] - check_returncode()
: 若 returncode 值为非零,则返回 CalledProcessError
.
3. subprocess.Popen
Popen
函数是 subprocess 的核心,在新进程运行子程序. 处理子进程的创建和管理.
3.1. 定义
函数定义如:
class subprocess.Popen(args,
bufsize=-1, #缓冲区大小;0-不使用缓冲区;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)
参考 suprocess.run 方法.
3.2. 示例
import subprocess
pn = subprocess.Popen('ls -lh', shell=True)
#或:
#pn = subprocess.Popen(['ls', '-lh'])
pn.returncode
pn.wait()
pn.returncode
pn = subprocess.Popen(["/usr/bin/git", "commit", "-m", "Fixes a bug."])
#subprocess.Popen(['/bin/sh', '-c', args[0], args[1], ...])
3.3. 对象方法
3.3.1. Popen.poll()
检查子进程是否结束. 正常返回是 returncode
; 否则返回 None.
3.3.2. Popen.wait(timeout=None)
等待子进程终止.
3.3.3. Popen.communicate(input, timeout)
和子进程交互,发送和读取数据.
返回值为元组 (stdout_data, stderr_data)
.
3.3.4. Popen.send_signal(signal)
发送信号到子进程.
3.3.5. Popen.terminate()
停止子进程.
3.3.6. Popen.kill()
杀掉子进程.
3.4. 示例
import time
import subprocess
def cmd(command):
subpn = subprocess.Popen(command,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
encoding="utf-8")
subpn.wait(2)
print(subpn.poll())
if subpn.poll() == 0:
print(subpn.communicate()[1])
else:
print("Failed")
#
cmd("nvcc --version")
cmd("exit 1")