Python标准库 - os (2) 进程管理
文章目录
- 3 进程管理
- 3.1 进程状态和控制
- 3.2 进程优先级
- 3.3 程序段控制
- 3.4 其他
- 4 创建子进程
- 4.1 创建子进程常见函数
- 4.2 spawn*族函数
- 4.3 exec*族函数
- 5 子进程管理
- 5.1 创建子进程触发事件
- 5.2 等待子进程执行完
- 5.3 子进程的状态
os模块提供了各种操作系统接口。包括环境变量、进程管理、进程调度、文件操作等方面。
这里整理了进程管理的方法。
参考:os模块官方文档
3 进程管理
创建和管理进程。
3.1 进程状态和控制
-
os.times
返回全局进程时间。
返回值是有5个属性的对象。user(用户时间)、system(系统时间)、children_user(所有子进程的用户时间)、children_system(所有子进程的系统时间)、elapsed(从过去的固定时间点起经过的真实时间)。
可以作为元组迭代这五个属性。>>> os.times() posix.times_result(user=0.01, system=0.0, children_user=0.0, children_system=0.0, elapsed=17890247.55)
-
os.pidfd_open(pid, flags=0)
返回一个指向设置了flags的进程pid的文件描述符。可用于执行无须竞争和信号的进程管理。 -
os.abort()
发送SIGABRT
信号到当前进程。 -
os.kill(pid, sig)
将信号sig发送至进程pid。 -
os.killpg(pgid, sig)
将信号sig发送给进程组pgid。 -
os._exit(n)
以状态码n退出进程。
标准退出方式是sys.exit(n)
。os._exit(n)
通常只用在os.fork()
生成的子进程中。
退出码常量 | 值 | 说明 |
---|---|---|
os.EX_OK | 0 | 没有发生错误 |
os.EX_USAGE | 64 | 命令使用不正确 |
os.EX_DATAERR | 65 | 输入数据不正确 |
os.EX_NOINPUT | 66 | 某个输入文件不存在或不可读 |
os.EX_NOUSER | 67 | 指定用户不存在 |
os.EX_NOHOST | 68 | 指定主机不存在 |
os.EX_UNAVAILABLE | 69 | 所需服务不可用 |
os.EX_SOFTWARE | 70 | 检测到内部软件错误 |
os.EX_OSERR | 71 | 检测到操作系统错误 |
os.EX_OSFILE | 72 | 系统文件不存在、无法打开或发生其他错误 |
os.EX_CANTCREAT | 73 | 无法创建用户指定的输出文件 |
os.EX_IOERR | 74 | 对文件进行读写时发生错误 |
os.EX_TEMPFAIL | 75 | 发生暂时性故障。 |
os.EX_PROTOCOL | 76 | 协议交换是非法、无效或无法解读的 |
os.EX_NOPERM | 77 | 没有足够的权限进行操作 |
os.EX_CONFIG | 78 | 配置错误 |
os.EX_NOTFOUND | 79 | 找不到条目 |
3.2 进程优先级
-
os.getpriority(which, who)
获取程序调度优先级。>>> os.getpriority(os.PRIO_USER, 0) -20 >>> os.getpriority(os.PRIO_PGRP, 0) 0 >>> os.getpriority(os.PRIO_PGRP, 31044) 0 >>> os.getpriority(os.PRIO_PROCESS, 31044) 0
-
os.setpriority(which, who, priority)
设置程序调度优先级。
参数which是os.PRIO_PROCESS
、os.PRIO_PGRP
或os.PRIO_USER
中的一个。
参数who是相对于which的值。 -
os.nice(increment)
进程的优先级增加指定值,返回新的优先级值。
涉及的常量说明:
os.PRIO_PROCESS
进程标识符os.PRIO_PGRP
进程组标识符os.PRIO_USER
用户ID
3.3 程序段控制
-
os.unshare(flags)
拆分进程执行上下文的部分内容,将其移入新创建的命名空间中。 -
os.setns(fd, nstype=0)
将当前线程与Linux命名空间重新关联。 -
os.plock(op)
把程序段锁定到内存中。op值决定哪些段被锁定。
3.4 其他
-
os.umask(mask)
设定当前数值掩码,并返回之前的掩码。>>> os.umask(2) 18
Linux系统在创建文件或目录时,用数值掩码来确定文件的访问权限。
$ umask 0022 $ umask -S u=rwx,g=rx,o=rx
umask值表示了需要从权限中去掉哪些权限,才是生成文件的权限值。上述的umask值生成可执行文件时,从全部权限
rwxrwxrwx
去掉-----w--w-
,文件权限为rwxr-xr-x
。 -
os.strerror(code)
根据错误码返回错误消息。未知错误码会引发ValueError。>>> os.strerror(0) 'Success' >>> os.strerror(1) 'Operation not permitted' >>> os.strerror(2) 'No such file or directory' >>> os.strerror(42) 'No message of desired type'
4 创建子进程
4.1 创建子进程常见函数
-
os.fork()
Fork出一个新进程。在子进程中返回0,父进程返回子进程的进程号。 -
os.forkpty()
Fork出一个子进程,使用新的伪终端用作子进程的控制终端。返回(pid, fd)
,子进程中pid为0,父进程中pid为新子进程的进程号。fd是伪终端主设备的文件描述符。>>> os.forkpty() (31261, 3)
-
os.popen(cmd, mode='r', buffering=-1)
打开一个通往接受命令cmd的管道。返回值是连接到该管道的已打开文件对象。
返回的文件对象只能读写文本字符串而不是字节串。
该方法基于subprocess.Popen
实现。 -
os.posix_spawn(path, argv, env, *, file_actions=None, setpgroup=None, resetids=False, setsid=False, setsigmask=(), setsigdef=(), scheduler=None)
包装C库的APIposix_spawn()
,用于创建进程。
path
为可执行文件的路径;argv
是运行时接受的参数列表;env
表示使用的进程环境,为None时使用当前进程的环境。file_actions
是一个元组组成的序列,描述对子进程中指定文件描述符采取的操作。setpgroup
参数设置子进程的进程组。设为0时,子进程的进程组ID等于其进程ID。为None时,子进程继承父进程的进程组ID。resetids
为True
时,子进程的有效UID和GID会重置为父进程的实际UID和GID。为False
时保留父进程的有效UID和GID。需要在可执行文件上启用设置用户ID和组ID权限。setid
为True
时,会为posix_spawn
新建一个会话ID。setsigmask
会把信号掩码设置为指定的信号集合。不设定时,子进程使用父进程的信号掩码。setdef
参数把集合中所有信号的操作重置为默认。scheduler
需要输入元组,其中有调度器策略和携带了调度器参数的sched_param
实例。file_actions
参数表示的元组序列,每个元组的第一个元素是指定的类型指示符。元组的可选格式及说明如下:
(os.POSIX_SPAWN_OPEN, fd, path, flags, mode)
,执行os.dup2(os.open(path, flagss, mode), fd)
;
(os.POSIX_SPAWN_CLOSE, fd)
,执行os.close(fd)
;
(os.POSIX_SPAWN_DUP2, fd, new_fd)
,执行os.dup2(fd, new_fd)
;
(os.POSIX_SPAWN_CLOSEFROM, fd)
,执行os.closerange(fd, INF)
; -
os.posix_spawnp(...)
包装C库的APIposix_spawnp()
。功能类似os.posix_spawn()
。 -
os.system(command)
在shell程序中执行命令。
通过C函数system()
实现。
如果命令产生输出,会发送到解释器的标准输出流。
返回值取决于具体系统。# CentOS >>> os.system("ps") PID TTY TIME CMD 30975 pts/0 00:00:00 bash 31646 pts/0 00:00:00 python3.7 32099 pts/0 00:00:00 ps 0 # Windows >>> os.system("ipconfig") Windows IP Configuration Wireless LAN adapter 本地连接* 1: ...
-
os.startfile(path[, operation][, arguments][, cwd][, show_cdm])
使用已关联的应用程序打开文件。仅Windows可用。
不指定operation
,类似于双击这个文件。operation
可选的值有open
、print
、edit
(针对文件)和explore
、find
(针对目录)。启动某个应用程序时,
arguments
会作为一个字符串传入。参数
cwd
用于指定工作目录,必须是绝对路径。path
的相对路径会据此解析。show_cmd
用于覆盖默认的窗口样式。
4.2 spawn*族函数
os.spawnl(mode, path, ...)
os.spawnle(mode, path, ..., env)
os.spawnlp(mode, file, ...)
os.spawnlpe(mode, file, ..., env)
os.spawnv(mode, path, args)
os.spawnve(mode, path, args, env)
os.spawnvp(mode, file, args)
os.spawnvpe(mode, file, args, env)
创建子进程,执行path或file指定的程序。
函数的l
和v
变体提供了不同的形参传递方式。形参数目固定时,使用l
变体依次传入参数;形参数目不定时,使用v
变体把参数以列表的形式传入。
结尾带有p
的函数变体会通过PATH
环境变量来定位程序file
。环境变化时,会应用新的PATH
。
不带有p
的函数变体的参数path
必须包含正确的路径。相对路径必须包含至少一个斜杠。
以e
结尾的函数变体允许输入env
,定义新进程的环境变量。不带e
的函数变体创建的新进程会使用当前进程的环境变量。
函数参数mode
可选的常量及说明:
常量 | 值 | 说明 |
---|---|---|
os.P_NOWAIT | 1 | 创建新进程后立即返回,返回值是进程ID |
os.P_NOWAITO | 3 | 创建新进程后立即返回,返回值是进程ID |
os.P_WAIT | 0 | 新进程正常退出,返回退出代码,被终止时返回-终止信号 |
os.P_DETACH | 4 | 类似os.P_NOWAIT ,但是新进程会与父进程的控制台脱离 |
os.P_OVERLAY | 2 | 新进程会替换当前进程 |
4.3 exec*族函数
os.execl(path, arg0, arg1, ...)
os.execle(path, arg0, arg1, ..., env)
os.execlp(file, arg0, arg1, ...)
os.execlpe(file, arg0, arg1, ..., env)
os.execv(path, args)
os.execve(path, args, env)
os.execvp(file, args)
os.execvpe(file, args, env)
以上函数都会执行新程序替换当前的进程。替换时,打开的文件对象和描述符都不会刷新,因此调用这类函数之前,最好使用sys.stdout.flush()
或os.fsync()
刷新它们。
5 子进程管理
5.1 创建子进程触发事件
-
os.register_at_fork(*, before=None, after_in_parent=None, after_in_child=None)
注册可调用对象。在使用os.fork()
或类似的进程克隆API派生新的子进程时,这些对象会运行。每个参数表示不同的调用点:
before
指定的函数在fork子进程前调用;
after_in_parent
在fork子进程后由父进程调用;
after_in_child
在fork子进程后由子进程调用。函数注册后无法注销。第三方C代码的
fork()
调用可能不会调用这些函数。
5.2 等待子进程执行完
-
os.wait()
等待子进程执行完后返回一个元组,包含pid和退出状态。
退出状态是一个16位数字,低字节是终止该进程的信号编号,高字节是退出状态码。
不存在可被等待的子进程时,会引发ChildProcessError
。 -
os.waitid(idtype, id, options)
idtype
可选4个常量,决定如何解读id。os.P_PID
,等待进程ID为id的子进程;os.P_PGID
,等待进程组ID为id的任何子进程;os.P_ALL
,等待任何子进程,忽略id;os.P_PIDFD
,等待以文件描述符id作为标识的子进程。
options
是多个旗标的组合。要求至少有os.WEXITED
、OS.WSTOPPED
、OS.WCONTINUED
中的一个。os.WNOHANG
、os.WNOWAIT
是可选旗标。返回值对象具有以下属性:si_pid(进程ID)、si_uid(子进程的实际用户ID)、si_signo(始终为
os.SIGCHLD
)、si_status(退出状态或信号编号,取决于si_code)、si_code(可能值os.CLD_EXITED
、os.CLD_KILLED
、os.CLD_DUMPED
、os.CLD_TRAPPED
、os.CLD_STOPPED
、os.CLD_CONTINUED
)。 -
os.waitpid(pid, options)
等待进程号为pid的子进程执行完,返回一个元组,内含进程ID和退出状态。
pid
大于0时,可以获取指定进程的状态信息。pid
为0时,获取当前进程所在进程组中所有子进程的状态。pid
为-1,获取当前进程的子进程的状态。pid
小于-1时,获取进程组-pid
中所有进程的状态。options
是多个旗标的OR组合。这个函数在Windows上有不同的行为:等待pid指定的进程执行完毕,返回一个元组,包含pid和左移8位后的退出状态码。pid小于等于0会抛出异常,整数options无效。
-
os.wait3(options)
功能和os.waitpid()
类似,不需要给进程id。返回一个三元组,包括子进程的id、退出状态和资源使用信息。 -
os.wait4(pid, options)
功能和os.waitpid()
类似。返回一个三元组,包括子进程的id、退出状态和资源使用信息。
上述的函数中,options
参数用到的旗标常量及其说明:
常量 | 说明 |
---|---|
os.WCONTINUED | 若子进程从上次报告之后从作业位置继续执行,该旗标会导致子进程被报告 |
os.WEXITED | 已终结的子进程被报告 |
os.WSTOPPED | 被信号发送停止的子进程被报告 |
os.WUNTRACED | 若子进程从上次被停止后再次被停止且未被报告,该旗标会导致子进程被报告 |
os.WNOHANG | 若没有任何子进程的状态是立即可用的,该旗标会使函数立即返回 |
os.WNOWAIT | 使os.waitid() 以可等待的状态离开子进程,后续的其他wait* 函数可以被调用来获取子进程状态信息 |
5.3 子进程的状态
-
os.WCOREDUMP(status)
如果进程生成核心转储,就返回True。
status参数是进程的状态码,即由os.system()
、os.wait()
、os.waitpid()
返回的状态码,用于确定进程上发生的操作。 -
os.WIFCONTINUED(status)
如果已停止的子进程通过传送SIGCONT获得恢复,则返回True。 -
os.WIFEXITED(status)
如果进程正常退出则返回True。 -
os.WIFSTOPPED(status)
如果进程正被追踪,且是通过传送一个信号停止的就返回True。 -
os.WIFSIGNALED(status)
进程通过一个信号来终止的则返回True。 -
os.WEXITSTATUS(status)
返回进程退出状态。仅在os.WIFEXITED()
为真时使用。 -
os.WSTOPSIG(status)
返回导致进程停止的信号。仅在os.WIFSTOPPED()
为真时使用。 -
os.WTERMSIG(status)
返回导致进程终止的信号的编号。仅在os.WIFSIGNALED()
为真时使用。 -
os.waitstatus_to_exitcode(status)
把等待状态转换为退出码
进程正常退出(os.IFEXITED(status)
为真),则返回进程退出状态(os.WEXITSTATUS(status)
),返回值大于等于0。
如果进程被信号终止(os.IFSIGNALED(status)
为真),则返回终止信号的相反值(-os.WTERRMSIG(status)
)。返回值小于0。如果进程正在被追踪或
os.waitpid()
的os.WUNTRACED
选项被调用,必须先检查os.WIFSTOPPED(status)
是否为真,为真时该函数不可用。在Windows上会返回status右移8位的结果。
以上是os模块关于进程管理的方法和常量整理。
该模块的其他内容参考:
os模块:环境变量、进程所属的用户和组
os模块:调度策略、系统信息