hello, 你们好,又到了小猿为你们分享技术的时间了.
css
近期拿到一个测试案例, 其中有一块是须要在测试案例中启动一个exe文件,而且在达到某个条件以后在shutdown掉,因而我就开始找寻解决方案(没错,百度以及谷歌),可是找到的试验起来要么达不到咱们预期的效果,要么就是由于权限的缘由能删除掉,总之三个字, 烦死了.python
好在最后找到了使用subprocess开启进程,使用命令 "taskkill /F /t /IM a.exe"命令结束进程,结果出乎的顺利.linux
虽然有点不三不四,可是目前而言,这个是最好的结果了.就先这样用着吧,谈到subprocess, 今天我们就分享一点关于subprocess模块相关的知识吧. shell
django
subprocess的做用是能够在当前程序中执行其余程序或者命令缓存
suprocess模块以及提供的Popen类,在这里介绍一下如何使用它在进程中建立一个新的子进程,还会有其余的方法与属性,它们在某些状况下很是方便和高效。ruby
首先是subprocess.Popen 类bash
经过调用微信
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)
数据结构
这个能够经过里面的参数详细制定子进程的环境,可是只有一个参数是必须的,即位置参数,不用着急,下面详细介绍剩余的参数
参数介绍:
args: 要执行的命令或者可执行文件的绝对路径,是一个由字符串组成的序列(一般指的是列表), 第一个元素是可执行程序的路径,剩下的是传递给这个程序的参数,若是只是单独的运行这个程序, 只是一个单纯的字符串就行,可是这个字符串必须是能使subprocess找到该指定文件.
bufsize:控制stdin, stdout, stderr 等参数指定的文件的缓冲,和打开文件的 open()函数中的参数 bufsize 含义相同。
executable: 这是替代参数args做为可执行程序的,若是该参数不是None的话.
stdin:指定子进程的标准输入.
stdout:指定子进程的标准输出.
stderr:指定子进程的标准错误输出.
对于 stdin, stdout和 stderr 而言,若是他们是 None(默认状况),那么子进程使用和父进程相同的标准流文件。
preexec_fn:默认是None,不然必须是一个函数或者可调用对象,在子进程中首先执行这个函数,而后再去执行为子进程指定的程序或Shell。
close_fds:布尔型变量,为 True 时,在子进程执行前强制关闭全部除 stdin,stdout和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()函数.固然另外一个更简便的方法是使用命令 'taskkill /F /t /IM a.exe'使用os.system的命令能够删除,不会出现权限不够关不了的问题,可是有点粗暴.
下面是在linux环境下执行的命令:
[root@localhost ~]# pythonPython 2.7.5 (default, Oct 30 2018, 23:45:53) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux2Type "help", "copyright", "credits" or "license" for more information. > import subprocess'ls -l',shell=True) > p = subprocess.Popen(28 > total drwxr-xr-x. 2 root root 6 Feb 14 2019 123-rw-r--r--. 1 root root 800 Feb 18 2019 --all-databases-rw-------. 1 root root 1301 Jan 26 2019 anaconda-ks.cfg-rwxr-xr-x 1 root root 164 Sep 8 21:28 bash.shdrwxr-xr-x. 3 root root 58 Feb 15 2019 django115drwxr-xr-x. 3 root root 56 Feb 15 2019 django2drwxr-xr-x. 9 root root 4096 Apr 16 2019 Envsdrwxr-xr-x. 2 root root 40 Dec 30 23:05 myfile-rwxrwxrwx. 1 root root 22 Apr 22 2019 myshell-rw-r--r--. 1 root root 0 Apr 23 2019 myso-rw-r--r--. 1 root root 403 Feb 15 2019 requirements.txt-rw-r--r--. 1 root root 26 May 11 2019 test.txtp = > p.returncode > p.wait()0 > p.returncode0
方法:
p.poll() 用于检查子进程P是否终止,返回p.returncode属性.
p.wait() 等待子进程,返回p.returncode属性 0 表明该子进程已经结束,注意,使用该方法会当即阻塞父进程,直到子进程结束
p.send_signal(signal) 向子进程发送信号
p.communicate(input=None), 和子进程进行交互式交流,将参数中的数据发送到子进程的stdin, 同时从子进程的stdout和stderr读取数据,直到EOF,该方法也会阻塞父进程.
注意点:子进程发送给的父进程的数据是缓存在内存中的,所以该方法不适合交换过大的数据, 在这这种方法只能经过管道和本身的子进程通讯,即建立子进程的参数stdin=subprocess.PIPE 才能经过该方法进行消息发送.
p.terminate() 终止子进程
p.kill() 杀死子进程
Popen对象的属性
如今先假设p是Popen的子进程,p的属性包括如下几项
p.pid 该子进程的pid
p.returncode 表示该子进程的返回状态,有多种状况
None - 子进程还没有结束
0 - 正常退出
大于0 - 子进程异常退出
小于 0 - 子进程被信号干掉
p.stdin, p.stdout, p.stderr 子进程对应的一些初始文件,若是在开启子进程时传入的参数有subprocess.PIPE,则这个属性是一个包裹了这个管道的file对象.
使用subprocess模块定义的异常
exception subprocess.CalledProcessError
该异常包含如下信息:
returncode:子进程的退出状态;
cmd:建立子进程时指定的命令;
output:若是是调用 check_output() 时抛出的该异常,这里包含子进程的输出,不然该属性为None。
关于该模块的内容,小猿暂时就先介绍到这吧.但愿能给你带来点些许的启发.也欢迎你们分享以及提出宝贵意见,您的意见我会所有查看并认真思考而且回复的呦.
本文分享自微信公众号 - IT民工技术之路(python_er)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。