python常用模块-调用系统命令模块(subprocess)
python常用模块-调用系统命令模块(subprocess)
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
subproces基本上就是为了取代os.system和os.spawn*模块的。当我们需要调用系统命令的时候,最险考虑的os模块。用os.system()和os.popen()来进行操作。但是这两个命令过于简单,不能完成一些复杂的操作,如给运行的命令提供输入或者读取命令的输出,判断该命令的运行状态,管理多个命令的并行等等。这时subprocess中的popen命令就能有效的完成我们需要的操作。
subprocess模块允许一个进程创建一个新的子进程,通过管道连接到子进程的stdin/stdout/stderr,获取子进程的返回值等操作。这个模块只是一个类:popen。
一.初识subprocess
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 import subprocess 8 9 cmd = subprocess.Popen("ping www.baidu.com",shell=True) #开启新的进程,执行“dir”命令。shell=True关键字是运行将命令和参数写在一起, 10 11 # cmd = subprocess.Popen(["ping","www.baidu.com"]) #如果不加shell=True关键字则需要将命令和参数分开写放在一个列表中。 12 13 cmd.wait() #需要等待上面开启的进程执行完毕才会继续执行下面的代码。 14 15 print("-"*50,"ending","-"*50) 16 17 print(cmd.poll()) #查看子进程状态 18 19 cmd.kill() #终止子进程 20 21 # cmd.send_signal() #向子进程发送信号 22 23 cmd.terminate() #终止子进程。 24 25 print(cmd.pid ) #查看子进程号 26 27 28 29 30 #以上代码执行结果如需: 31 32 ���� Ping www.baidu.com [61.135.169.125] ���� 32 �ֽڵ�����: 33 ���� 61.135.169.125 �Ļظ�: �ֽ�=32 ʱ��=7ms TTL=57 34 ���� 61.135.169.125 �Ļظ�: �ֽ�=32 ʱ��=3ms TTL=57 35 ���� 61.135.169.125 �Ļظ�: �ֽ�=32 ʱ��=7ms TTL=57 36 ���� 61.135.169.125 �Ļظ�: �ֽ�=32 ʱ��=4ms TTL=57 37 38 61.135.169.125 �� Ping ͳ����Ϣ: 39 ���ݰ�: �ѷ��� = 4���ѽ��� = 4����ʧ = 0 (0% ��ʧ)�� 40 �����г̵Ĺ���ʱ��(�Ժ���Ϊ��λ): 41 ��� = 3ms��� = 7ms��ƽ�� = 5ms 42 -------------------------------------------------- ending -------------------------------------------------- 43 0 44 372
二.进程间通信-子进程的文本流控制
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 import subprocess 8 9 10 11 cmd = subprocess.Popen("dir",shell=True,stdout=subprocess.PIPE) #将输出的内容传给“PIPE”,也就是我们常说的管道。 12 13 print(cmd.stdout.read().decode("gbk")) #将管道的内容读取出来。 14 15 16 17 18 19 #以上代码执行结果如下: 20 驱动器 E 中的卷是 应用程序存放处 21 卷的序列号是 FAFC-64CF 22 23 E:\Code\pycharm\文件存放处\python学习笔记\Day12 的目录 24 25 2018/03/16 22:37 <DIR> . 26 2018/03/16 22:37 <DIR> .. 27 2018/03/16 19:59 816 1.configparser模块-创建文件.py 28 2018/03/16 20:07 1,150 2.读操作.py 29 2018/03/16 20:21 464 3.修改配置文件.py 30 2018/03/16 20:26 728 4.configparser删除的实例.py 31 2018/03/16 22:37 1,252 5.subprocess模块.py 32 2018/03/16 22:36 492 6.进程间通信-子进程的文本流控制.py 33 2018/03/16 20:26 141 cfg.ini 34 2018/03/15 21:38 82 上课地址: 35 8 个文件 5,125 字节 36 2 个目录 50,547,294,208 可用字节
三.subprocess.run实例
subprocess.run调用shell命令,只能保存执行后的状态,不能保存命令的执行结果!
1 #不含参数的调用linux命令的方法 2 >>> a = subprocess.run("df") 3 Filesystem 1K-blocks Used Available Use% Mounted on 4 /dev/sda2 8854456 4170968 4227040 50% / 5 tmpfs 502172 228 501944 1% /dev/shm 6 /dev/sda1 289293 28463 245470 11% /boot 7 8 #含参数的调用linux命令的方法 9 >>> a = subprocess.run(["df","-h"]) 10 Filesystem Size Used Avail Use% Mounted on 11 /dev/sda2 8.5G 3.8G 4.3G 48% / 12 tmpfs 491M 228K 491M 1% /dev/shm 13 /dev/sda1 283M 28M 240M 11% /boot 14 >>> 15 16 17 18 #调用复杂的linux命令的方法,需要加“shell=True”,表示将前面引号的内容放在一个终端(terminal)去执行,需要注意的是这个不能保存命令输出的结果,而是保存命令执行的结果哟!一般非“0”就表示命令没有执行成功,而结果是“0”表示执行命令实成功的,但是命令的输出结果是无法保存的!切记! 19 >>> a = subprocess.run("df -h | grep /dev/sda1",shell=True) 20 /dev/sda1 283M 28M 240M 11% /boot 21 >>> a.returncode 22 0
四.subprocess.call与subprocess.check_call函数的调用方法
执行命令,返回命令的执行状态,“0” or 非 “0”。
1 #执行命令,返回命令执行状态 , 0 or 非0 2 >>> retcode = subprocess.call(["ls", "-l"]) 3 total 96 4 -rw-------. 1 root root 3321 Oct 13 10:26 anaconda-ks.cfg 5 drwxr-xr-x. 2 root root 4096 Oct 13 22:03 Desktop 6 drwxr-xr-x. 2 root root 4096 Oct 13 22:03 Documents 7 drwxr-xr-x. 2 root root 4096 Oct 13 22:03 Downloads 8 -rw-r--r--. 1 root root 41433 Oct 13 10:26 install.log 9 -rw-r--r--. 1 root root 9154 Oct 13 10:24 install.log.syslog 10 drwxr-xr-x. 2 root root 4096 Oct 13 22:03 Music 11 drwxr-xr-x. 2 root root 4096 Oct 13 22:03 Pictures 12 drwxr-xr-x. 2 root root 4096 Oct 13 22:03 Public 13 drwxr-xr-x. 2 root root 4096 Oct 13 22:03 Templates 14 drwxr-xr-x. 2 root root 4096 Oct 13 22:03 Videos 15 >>> 16 17 18 #执行命令,如果命令结果为0,就正常返回,否则抛异常 19 >>> subprocess.check_call(["ls", "-l"]) 20 total 96 21 -rw-------. 1 root root 3321 Oct 13 10:26 anaconda-ks.cfg 22 drwxr-xr-x. 2 root root 4096 Oct 13 22:03 Desktop 23 drwxr-xr-x. 2 root root 4096 Oct 13 22:03 Documents 24 drwxr-xr-x. 2 root root 4096 Oct 13 22:03 Downloads 25 -rw-r--r--. 1 root root 41433 Oct 13 10:26 install.log 26 -rw-r--r--. 1 root root 9154 Oct 13 10:24 install.log.syslog 27 drwxr-xr-x. 2 root root 4096 Oct 13 22:03 Music 28 drwxr-xr-x. 2 root root 4096 Oct 13 22:03 Pictures 29 drwxr-xr-x. 2 root root 4096 Oct 13 22:03 Public 30 drwxr-xr-x. 2 root root 4096 Oct 13 22:03 Templates 31 drwxr-xr-x. 2 root root 4096 Oct 13 22:03 Videos 32 0 33 >>>
五.subprocess.getstatusoutput函数的调用方法
接收字符串格式命令,返回元组形式,第1个元素是执行状态,第2个是命令结果
1 >>> subprocess.getstatusoutput('ls /bin/pwd') 2 (0, '/bin/pwd') 3 >>>
六.subprocess.getoutput函数调用方法
接收字符串格式命令,并返回结果.
1 >>> subprocess.getoutput('ifconfig | grep eth0') 2 'eth0 Link encap:Ethernet HWaddr 00:0C:29:D4:DB:87 ' 3 >>>
七.subprocess.check_output函数调用方法
执行命令,并返回结果,注意是返回结果,不是打印,下例结果返回给res.
1 >>> res=subprocess.check_output(['pwd']) 2 >>> res 3 b'/root\n' 4 >>>
八.subprocess.Popen函数用法
上面那些方法,底层都是封装的subprocess.Popen
1 >>> p = subprocess.Popen("df -h|grep /dev/sda1",stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True) 2 >>> p.stdout.read() 3 b'/dev/sda1 283M 28M 240M 11% /boot\n' 4 >>> 5 6 “”“ 7 注意: 8 我们来对第一行的进行讲解一下 9 subprocess.Popen表示打开一个终端(只是启动一个进程),stdin=subprocess.PIPE表示输入通过subprocess.PIPE这个管道传输,stdout=subprocess.PIPE表示输出也通过subprocess.PIPE这个管道传输,stderr=subprocess.PIPE同理。 10 ”“”
九.检查命令是否执行完毕
1.poll()方法调用案例【不需要等】
1 >>> p = subprocess.Popen("top -bn 5",stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True) 2 >>> p.poll() 3 >>> p.poll() 4 >>> p.poll() 5 >>> p.poll() 6 >>> p.poll() 7 >>> p.poll() 8 0 9 >>> p.poll() 10 0 11 >>> 12 ‘’‘ 13 poll() 14 Check if child process has terminated. Returns returncode 15 ’‘’
2.wait()方法调用案例【需要等】返回执行状态
1 >>> p = subprocess.Popen("top -bn 5",stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True) 2 >>> p.wait() 3 0 4 >>> 5 6 ''' 7 wait() 8 Wait for child process to terminate. Returns returncode attribute. 9 '''
3.terminate()方法调用案例,直接杀掉启动进程
1 >>> p = subprocess.Popen("top -bn 5",stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True) 2 >>> p.poll() 3 >>> p.terminate() 4 >>> p.poll() 5 143 6 7 ''' 8 terminate() 杀掉所启动进程,此时p.poll返回值应该是非“0”,因为不是正常结束的!没有执行完毕就被杀掉了。 9 '''
4.communicate()函数调用方法
1 >>> p = subprocess.Popen("df -h;sleep 100",stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True) 2 >>> p.poll() 3 >>> p.poll() 4 >>> p.communicate(timeout=2) 5 Traceback (most recent call last): 6 File "<stdin>", line 1, in <module> 7 File "/usr/local/lib/python3.5/subprocess.py", line 1068, in communicate 8 stdout, stderr = self._communicate(input, endtime, timeout) 9 File "/usr/local/lib/python3.5/subprocess.py", line 1699, in _communicate 10 self._check_timeout(endtime, orig_timeout) 11 File "/usr/local/lib/python3.5/subprocess.py", line 1094, in _check_timeout 12 raise TimeoutExpired(self.args, orig_timeout) 13 subprocess.TimeoutExpired: Command 'df -h;sleep 100' timed out after 2 seconds 14 >>> 15 16 ‘’‘ 17 communicate() 等待任务结束,我们需要在里面添加一个参数,默认单位是“s”,如果程序执行时间超过指定的时间就会抛出一个“TimeoutExpired”的字样哟,不过我们可以用异常处理来吧这个错误解决掉! 18 ’‘’
5.preexec_fn参数调用案例
1 >>> def name(): 2 ... print("my name is yinzhengjie!") 3 ... 4 >>> p = subprocess.Popen("pwd",stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE, preexec_fn=name) >>> p.stdout.read() 5 b'my name is yinzhengjie!\n/root\n' 6 >>> 7 8 ‘’‘ 9 preexec_fn:只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用,运行结果见上例。 10 ’‘’
6.cwd参数调用案例
1 >>> p = subprocess.Popen("pwd",cwd="/usr/local",stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE) 2 >>> p.stdout.read() 3 b'/usr/local\n' 4 >>> 5 6 ''' 7 cwd:用于设置子进程的当前目录 8 '''
7.env参数调用案例
1 >>> p = subprocess.Popen("echo $name_str",cwd="/usr/local",shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,env={"name_str":"yinzhengjie"}) 2 >>> p.stdout.read() 3 b'yinzhengjie\n' 4 >>> 5 ‘’‘ 6 提示: 7 env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。 8 ’‘’