subprocess模块最全笔记
文章目录
- subprocess
- subprocess.Popen 类
- Popen 对象的属性
- Popen 对象的方法
- subprocess模块的其他方法
- subprocess模块的其他属性
- subprocess模块定义的异常
- os.system()
- os.popen()
- subprocess.run()
- subprocess.getstatusoutput()
- subprocess.getoutput()
- terminate()
- pid
subprocess
使用 Popen 可以在Python进程中创建子进程,如果只对子进程的执行退出状态感兴趣,可以调用 subprocess.call()
函数,如果想通过异常处理机制解决子进程异常退出的情形,可以考虑使用 subprocess.check_call()
和 subprocess.check_output
。如果希望获得子进程的输出,可以调用
subprocess.check_output()
,但 Popen() 无疑是功能最强大的。
subprocess模块的缺陷在于默认提供的父子进程间通信手段有限,只有管道;同时创建的子进程专门用来执行外部的程序或命令。
Linux下进程间通信的手段很多,子进程也完全可能从创建之后继续调用
subprocess.Popen 类
通过调用:
subprocess.Popen(args, bufsize=0, executable=None, stdin=None,stdout=None, stderr=None, preexec_fn=None, close_fds=False,shell=False, cwd=None, env=None, universal_newlines=False,startupinfo=None, creationflags=0)1234
创建并返回一个子进程,并在这个进程中执行指定的程序。
实例化 Popen 可以通过许多参数详细定制子进程的环境,但是只有一个参数是必须的,即位置参数 args ,下面也会详细介绍剩余的具名参数。
参数介绍:
args
:要执行的命令或可执行文件的路径。一个由字符串组成的序列(通常是列表),列表的第一个元素是可执行程序的路径,剩下的是传给这个程序的参数,如果没有要传给这个程序的参数,args 参数可以仅仅是一个字符串。bufsize
:控制stdin, stdout, stderr
等参数指定的文件的缓冲,和打开文件的 open()函数中的参数bufsize 含义相同。executable
:如果这个参数不是 None,将替代参数 args 作为可执行程序;stdin
:指定子进程的标准输入;stdout
:指定子进程的标准输出;stderr
:指定子进程的标准错误输出;
对于stdin, stdout
和stderr
而言,如果他们是 None(默认情况),那么子进程使用和父进程相同的标准流文件。
父进程如果想要和子进程通过communicate()
方法通信,对应的参数必须是subprocess.PIPE
(见下文例4);
当然stdin, stdout 和 stderr
也可以是已经打开的 file 对象,前提是以合理的方式打开,比如 stdin 对应的文件必须要可读等。preexec_fn
:默认是None,否则必须是一个函数或者可调用对象,在子进程中首先执行这个函数,然后再去执行为子进程指定的程序或Shell。close_fds
:布尔型变量,为 True 时,在子进程执行前强制关闭所有除stdin,stdou
t和stderr
外的文件;shell
:布尔型变量,明确要求使用shell运行程序,与参数executable
一同指定子进程运行在什么Shell
中——如果executable=None 而 shell=True
,则使用/bin/sh
来执行args
指定的程序;也就是说,Python首先起一个shell,再用这个shell来解释指定运行的命令。cwd
:代表路径的字符串,指定子进程运行的工作目录,要求这个目录必须存在;env
:字典,键和值都是为子进程定义环境变量的字符串;universal_newline
:布尔型变量,为 True 时,stdout 和 stderr 以通用换行(universal
newline)模式打开,startupinfo
:见下一个参数;creationfalgs
:最后这两个参数是Windows中才有的参数,传递给Win32的CreateProcess API调用。
同 Linux 中创建子进程类似,父进程创建完子进程后,并不会自动等待子进程执行,父进程在子进程之前退出将导致子进程成为孤儿进程,孤儿进程统一由 init 进程接管,负责其终止后的回收工作。
如果父进程在子进程之后终止,但子进程终止时父进程没有进行最后的回收工作,子进程残留的数据结构称为僵尸进程。大量僵尸进程将耗费系统资源,因此父进程及时等待和回收子进程是必要的,除非能够确认自己比子进程先终止,从而将回收工作过渡给 init 进程。
这个等待和回收子进程的操作就是wait()函数,下文中将会介绍。
例1:
# 创建一个子进程,然后执行一个简单的命令>>> import subprocess
>>> p = subprocess.Popen('ls -l', shell=True)
>>> total 164
-rw-r--r-- 1 root root 133 Jul 4 16:25 admin-openrc.sh
-rw-r--r-- 1 root root 268 Jul 10 15:55 admin-openrc-v3.sh
...
>>> p.returncode
>>> p.wait()
0
>>> p.returncode
0
# 这里也可以使用 p = subprocess.Popen(['ls', '-cl']) 来创建子进程。1234567891011121314
Popen 对象的属性
Popen创建的子进程有一些有用的属性,假设 p 是 Popen 创建的子进程,p 的属性包括:
1.
p.pid
子进程的PID
2.p.returncode
该属性表示子进程的返回状态,returncode可能有多重情况:
None
—— 子进程尚未结束;
==0
—— 子进程正常退出;
< 0
—— 子进程被信号杀掉了。
大于 0
—— 子进程异常退出,returncode对应于出错码;
3.p.stdin, p.stdout, p.stderr
子进程对应的一些初始文件,如果调用Popen()的时候对应的参数是subprocess.PIPE
,则这里对应的属性是一个包裹了这个管道的 file 对象
,
Popen 对象的方法
1.
p.poll()
检查子进程p
是否已经终止,返回p.returncode
属性 (参考下文 Popen 对象的属性);
2.p.wait()
等待子进程 p 终止,返回p.returncode
属性;注意:wait()
立即阻塞父进程,直到子进程结束!
3.p.communicate(input=None)
和子进程p
交流,将参数input
(字符串)中的数据发送到子进程的stdin
,同时从子进程的stdout 和 stderr
读取数据,直到EOF
。
返回值:
二元组(stdoutdata, stderrdata)
分别表示从标准出和标准错误
中读出的数据。 父进程调用p.communicate()
和子进程通信有以下限制:
(1) 只能通过管道和子进程通信,也就是说,只有调用Popen()
创建子进程的时候参数
stdin=subprocess.PIPE
,才能通过p.communicate(input)
向子进程的 stdin 发送数据;只有参数
stout 和 stderr
也都为subprocess.PIPE
,才能通过p.communicate()
从子进程接收数据,否则接收到的二元组中,对应的位置是None。
(2)父进程从子进程读到的数据缓存在内存中,因此commucate()
不适合与子进程交换过大的数据。
注意:
communicate()
立即阻塞父进程,直到子进程结束!4.
p.send_signal(signal)
向子进程发送信号 signal;5
.p.terminate()
终止子进程 p ,等于向子进程发送 SIGTERM 信号;6
.p.kill()
杀死子进程 p ,等于向子进程发送 SIGKILL 信号;
subprocess模块的其他方法
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
父进程直接创建子进程执行程序,然后等待子进程完成
返回值:
call() 返回子进程的 退出状态 即child.returncode
属性;subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
父进程直接创建子进程执行程序,然后等待子进程完成,具体可以使用的参数,参考上文 Popen 类的介绍。
返回值:
无论子进程是否成功,该函数都返回 0;但是
如果子进程的退出状态不是0,check_call() 抛出异常 CalledProcessError
,异常对象中包含了child.returncode
对应的返回码。
例2:
check_call()正常与错误执行命令
>>> p = subprocess.check_call(['ping' ,'-c', '2', 'www.baidu.com'])
PING www.a.shifen.com (220.181.111.188) 56(84) bytes of data.
64 bytes from 220.181.111.188: icmp_seq=1 ttl=42 time=37.4 ms
64 bytes from 220.181.111.188: icmp_seq=2 ttl=42 time=37.3 ms--- www.a.shifen.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 37.335/37.410/37.486/0.207 ms
>>> print p
<strong>0</strong>
>>> p = subprocess.check_call(['ping' ,'-c', '4', 'www.!@$#@!(*^.com'])
ping: unknown host www.!@$#@!(*^.com
Traceback (most recent call last):File "<stdin>", line 1, in <module>File "/usr/lib/python2.7/subprocess.py", line 540, in check_callraise CalledProcessError(retcode, cmd)
subprocess.<strong>CalledProcessError</strong>: Command '['ping', '-c', '4', 'www.!@$#@!(*^.com']' returned non-zero exit status 2
>>> print p
<strong>0
</strong>1234567891011121314151617181920
3.subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)
父进程直接创建子进程执行程序,以字符串的形式返回子进程的输出。
返回值:
字符串形式的子进程的输出结果,但是,
如果子进程的 退出状态 不是0,那么抛出异常 CalledProcessError,异常对象中包含了 child.returncode 对应的返回码。
注意:
check_output()
的函数签名中没有参数 stdout,调用该方法时,子进程的输出默认就返回给父进程。
例3:
check_output() 调用的子进程正常与错误退出
subprocess.check_output(["echo", "Hello World!"])
'Hello World!\n'
subprocess.check_output("exit 1", shell=True)
Traceback (most recent call last):...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1123456
注意:
使用上面提到的三个方法:call()、check_call() 和 check_output()
时,尽量不要将参数 stderr 和 stdout 设置为 subprocess.PIPE,
这几个函数默认都会等待子进程完成,子进程产生大量的输出数据如果造成管道堵塞,父进程再等待子进程完成可能造成死锁。
subprocess模块的其他属性
1.
subprocess.PIPE
调用本模块提供的若干函数时,作为 std* 参数的值,为标准流文件打开一个管道。
例4:
使用管道连接标准流文件
import subprocess
child1 = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE)
child2 = subprocess.Popen(['wc', '-l'], stdin=child1.stdout, stdout=subprocess.PIPE)
out = child2.communicate()
child1.wait()
child2.wait()
print(out)
# 这里将子进程 child1 的标准输出作为子进程 child2 的标准输入,父进程通过 communicate() 读取 child2 的标准输出后打印。12345678
subprocess.STDOUT
调用本模块提供的若干函数时,作为 stderr 参数的值,将子进程的标准错误输出打印到标准输出。
subprocess模块定义的异常
exception subprocess.CalledProcessError` (1)什么时候可能抛出该异常: `调用check_call() 或 check_output() ,子进程的退出状态不为 0 时。` (2)该异常包含以下信息: `returncode:子进程的退出状态; cmd:创建子进程时指定的命令; output:如果是调用 check_output()时抛出的该异常,这里包含子进程的输出,否则该属性为None。
os.system()
执行操作系统的命令,将结果输出到屏幕,只返回命令执行状态(0:成功,非 0 :失败)
>>> import os>>> a =os.system("df -Th")文件系统 类型 容量 已用 可用 已用% 挂载点devtmpfs devtmpfs 126G 0126G 0% /devtmpfs tmpfs 126G 313M 126G 1% /dev/shmtmpfs tmpfs 126G 107M 126G 1% /runtmpfs tmpfs 126G 0126G 0% /sys/fs/cgroup/dev/sda3 xfs 1.1T 57G 1.1T 6% //dev/sda1 xfs 397M 202M 195M 51% /boottmpfs tmpfs 26G 0 26G 0% /run/user/0tmpfs tmpfs 26G 0 26G 0% /run/user/1003>>> a0 #0表示执行成功>>> res =os.system("list")sh: list: 未找到命令>>> res32512 #非0表示执行错误
os.popen()
执行操作系统的命令,会将结果保存在内存当中,可以用read()
方法读取出来
>>> import os# 将结果保存到内存中>>> res =os.popen("ls -l")>>> print (res)<os._wrap_close object at 0x7f73a767f3c8># 用read()读取内容>>> print (res.read())总用量 370984-rw-r--r--1root root 46412月 2414:33 1.py-rw-r--r--1root root 48012月 2414:44 2.py-rw-r--r--1root root 8812月 2414:44 error.txtdrwxr-xr-x 2smgadmin smgadmin 819212月 2415:26 hsperfdata_smgadmin-rw-r--r--1root root 37985963012月 1617:01 新模型.zip
subprocess.run()
>>> import subprocess# python解析则传入命令的每个参数的列表>>> subprocess.run(["df","-h"])文件系统 容量 已用 可用 已用% 挂载点devtmpfs 126G 0126G 0% /devtmpfs 126G 151M 126G 1% /dev/shmtmpfs 126G 107M 126G 1% /runtmpfs 126G 0126G 0% /sys/fs/cgroup/dev/sda3 1.1T 57G 1.1T 6% //dev/sda1 397M 202M 195M 51% /boottmpfs 26G 0 26G 0% /run/user/0tmpfs 26G 0 26G 0% /run/user/1003CompletedProcess(args=['df', '-h'], returncode=0)# 需要交给Linux shell自己解析,则:传入命令字符串,shell=True>>> subprocess.run("df -h|grep /dev/sda1",shell=True)/dev/sda1 397M 202M 195M 51% /bootCompletedProcess(args='df -h|grep /dev/sda1', returncode=0)
subprocess.getstatusoutput()
接受字符串形式的命令,返回 一个元组形式的结果,第一个元素是命令执行状态,第二个为执行结果
#执行正确>>> subprocess.getstatusoutput('pwd')(0, '/tmp')#执行错误>>> subprocess.getstatusoutput('pd')(127, '/bin/sh: pd: 未找到命令')
subprocess.getoutput()
接受字符串形式的命令,查看执行结果
>>> subprocess.getoutput('pwd')'/tmp'
terminate()
结束进程
import subprocess
res =subprocess.Popen("sleep 20;echo 'hello'",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
res.terminate()
res.stdout.read()
pid
获取当前执行子shell的程序的进程号
import subprocess
res =subprocess.Popen("sleep 5;echo 'hello'",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
res.pid # 获取这个linux shell 的 进程号59858
subprocess模块最全笔记相关推荐
- Python Re 模块超全解读!详细
内行必看!Python Re 模块超全解读! 2019.08.08 18:59:45字数 953阅读 121 re模块下的函数 compile(pattern):创建模式对象 > import ...
- Python常用模块之subprocess模块
当我们需要调用系统的命令的时候,最先考虑的os模块.用os.system()和os.popen()来进行操作. 但是这两个命令过于简单,不能完成一些复杂的操作,如给运行的命令提供输入或者读取命令的输出 ...
- re的剩余模块和subprocess模块
今天学习了re的剩余模块和subprocess模块 一.re的剩余模块 #[] 范围匹配 中间 用-来连接 re.findall('[a-zA-Z0-9]','a ab asdf sadf asdf ...
- re模块剩余和subprocess模块
re模块 import re# [] 范围匹配 中间 用-来连接 # re.findall("[a-zA-Z0-9]","a ab abc abcd a123c" ...
- python subprocess pipe_Python的subprocess模块总结
subprocess意在替代其他几个老的模块或者函数,比如:os.system os.spawn* os.popen* popen2.* commands.* subprocess最简单的用法就是调用 ...
- python subprocess模块 命令执行
subprocess模块中定义了一个Popen类,通过它可以来创建进程,并与其进行复杂的交互.查看一下它的构造函数: __init__(self, args, bufsize=0, executabl ...
- Python subprocess模块
subprocess subprocess模块介绍 subprocess模块是一个可以将系统内的命令结果赋值给变量并打印, 还可以输出命令执行状态,subprocess可以单独将 命令输出结果与执行状 ...
- python subprocess 模块
subprocess 模块中有一个功能Popen , 可以在代码中调用系统的命令 其功能比os.system 更加强大 代码示例: command = 'python -u %s/generalMak ...
- python3中使用subprocess模块执行外部命令
一. subprocess模块介绍 subprocess模块可以替代os模块下的os.system和os.popen等操作方法 subprocess模块在python2和python3上的使用上有一定 ...
最新文章
- KL 损失的边界框回归
- python篮球-用Python把蔡徐坤打篮球视频转换成字符动画!
- python怎么安装numpy库-Python NumPy库安装使用笔记
- 剑指offer(1-10题)详解
- mysql 5.0 乱码_MySQL 5.0.16 乱码问题处理办法
- python3写冒泡排序_使用python3实现冒泡排序、选择排序和快速排序
- 傅里叶变换处理sar图像_SAR和ISAR雷达的基础知识
- 作者:王文生,中国农业科学院农业信息研究所副所长、研究员。
- [分享] Flask 网络开发经典书籍: Flask Web Development
- node安装以后npm下载失败全套处理方案
- 教孩子学编程python pdf_教孩子学编程 PYTHON语言版 PDF_Python教程
- PHP学习之如何写一个项目?需求分析
- 六款国产杀毒软件资源占用测试,八款杀毒软件横向评测:系统资源占用篇
- 微信小程序星星评分代码片段(含半星)
- OpenWrt固件实现路由器定时重启方法
- PHP里把括号变成英文的方法,php怎么去除括号
- 平台云基石-CoreOS之集群篇(无需互联网)
- 想进世界顶尖投行 那我该上什么样的学校?
- 判断两个无环单向链表/有环单向链表是否相交,并返回相交节点
- 计算机的数学要求(?转)