对子进程的运行时间做限制,当超时时强制终止
终止运行超时的进程
subprocess 模块主要用于创建子进程,并连接它们的输入、输出和错误管道,获取它们的返回状态,在某种特殊情况下,我们需要对子进程的运行时间做限制,当超时时强制终止并获取输出。
subprocess 模块首先推荐使用的是它的 run
方法,更高级的用法是使用 Popen
。
Popen
方法语法格式如下:
1 | 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=False, startupinfo=None, creationflags=0,restore_signals=True, start_new_session=False, pass_fds=(),*, encoding=None, errors=None) |
常用参数:
- args:表示要执行的命令,可以是字符串或者序列类型(如:list,元组)
- bufsize:缓冲区大小。当创建标准流的管道对象时使用,默认-1。
0:不使用缓冲区
1:表示行缓冲,仅当universal_newlines=True时可用,也就是文本模式
正数:表示缓冲区字节大小
负数:表示使用系统默认的缓冲区大小。 - stdin、stdout 和 stderr:子进程的标准输入、输出和错误。其值可以是 subprocess.PIPE、subprocess.DEVNULL、一个已经存在的文件描述符、已经打开的文件对象或者 None。subprocess.PIPE 表示为子进程创建新的管道。subprocess.DEVNULL 表示使用 os.devnull。默认使用的是 None,表示什么都不做。另外,stderr 可以合并到 stdout 里一起输出。
- timeout:设置命令超时时间。如果命令执行时间超时,子进程将被杀死,并弹出 TimeoutExpired 异常。
- check:如果该参数设置为 True,并且进程退出状态码不是 0,则弹 出 CalledProcessError 异常。
- encoding: 如果指定了该参数,则 stdin、stdout 和 stderr 可以接收字符串数据,并以该编码方式编码。否则只接收 bytes 类型的数据。
- shell:如果该参数为 True,将通过操作系统的 shell 执行指定的命令(bash或cmd)。
- cwd:用于设置子进程的当前目录。
- env:用于指定子进程的环境变量。如果 env = None,子进程的环境变量将从父进程中继承。
直接用 timeout 参数为何不能实现?
当运行的命令自身超过这个时间限制时,不会触发 TimeoutExpired 异常。这是因为 subprocess.Popen 的 timeout 参数是设置子进程的超时时间,而不是执行的命令的超时时间,所以当执行的命令自身超过此时间限制时无法通过 timeout 参数来实现。
解决方案
Timer(定时器)是 Thread 的派生类,用于在指定时间后调用一个方法。
参数介绍:
- interval — 定时器间隔,间隔多少秒之后启动定时器任务(单位:秒);
- function — 线程函数;
- args — 线程参数,可以传递元组类型数据,默认为空(缺省参数);
- kwargs — 线程参数,可以传递字典类型数据,默认为空(缺省参数);
1 | import subprocess |