一、subprocess以及常用的封装函数
运行python的时候,我们都是在创建并运行一个进程。像Linux进程那样,一个进程可以fork一个子进程,并让这个子进程exec另外一个程序。在Python中,我们通过标准库中的subprocess包来fork一个子进程,并运行一个外部的程序。
subprocess包中定义有数个创建子进程的函数,这些函数分别以不同的方式创建子进程,所以我们可以根据需要来从中选取一个使用。另外subprocess还提供了一些管理标准流(standard stream)和管道(pipe)的工具,从而在进程间使用文本通信。

subprocess.call()
父进程等待子进程完成
返回退出信息(returncode,相当于Linux exit code)

subprocess.check_call()
父进程等待子进程完成
返回0
检查退出信息,如果returncode不为0,则举出错误subprocess.CalledProcessError,该对象包含有returncode属性,可用try…except…来检查

subprocess.check_output()
父进程等待子进程完成
返回子进程向标准输出的输出结果
检查退出信息,如果returncode不为0,则举出错误subprocess.CalledProcessError,该对象包含有returncode属性和output属性,output属性为标准输出的输出结果,可用try…except…来检查。

这三个函数的使用方法相类似,下面来以subprocess.call()举例说明:

代码如下:
>>> import subprocess
>>> retcode = subprocess.call(["ls", "-l"])
#和shell中命令ls -a显示结果一样
>>> print retcode
0

将程序名(ls)和所带的参数(-l)一起放在一个表中传递给subprocess.call()

shell默认为False,在Linux下,shell=False时, Popen调用os.execvp()执行args指定的程序;shell=True时,如果args是字符串,Popen直接调用系统的Shell来执行args指定的程序,如果args是一个序列,则args的第一项是定义程序命令字符串,其它项是调用系统Shell时的附加参数。

上面例子也可以写成如下:

代码如下:
>>> retcode = subprocess.call("ls -l",shell=True)

在Windows下,不论shell的值如何,Popen调用CreateProcess()执行args指定的外部程序。如果args是一个序列,则先用list2cmdline()转化为字符串,但需要注意的是,并不是MS Windows下所有的程序都可以用list2cmdline来转化为命令行字符串。

subprocess.Popen()

代码如下:
class 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)

实际上,上面的几个函数都是基于Popen()的封装(wrapper)。这些封装的目的在于让我们容易使用子进程。当我们想要更个性化我们的需求的时候,就要转向Popen类,该类生成的对象用来代表子进程。

与上面的封装不同,Popen对象创建后,主程序不会自动等待子进程完成。我们必须调用对象的wait()方法,父进程才会等待 (也就是阻塞block),举例:

代码如下:
>>> import subprocess
>>> child = subprocess.Popen(['ping','-c','4','blog.linuxeye.com'])
>>> print 'parent process'

从运行结果中看到,父进程在开启子进程之后并没有等待child的完成,而是直接运行print。

对比等待的情况:

代码如下:
>>> import subprocess
>>> child = subprocess.Popen('ping -c4 blog.linuxeye.com',shell=True)
>>> child.wait()
>>> print 'parent process'

从运行结果中看到,父进程在开启子进程之后并等待child的完成后,再运行print。
此外,你还可以在父进程中对子进程进行其它操作,比如我们上面例子中的child对象:代码如下:

child.poll() # 检查子进程状态
child.kill() # 终止子进程
child.send_signal() # 向子进程发送信号
child.terminate() # 终止子进程

子进程的PID存储在child.pid
二、子进程的文本流控制
子进程的标准输入、标准输出和标准错误如下属性分别表示:

代码如下:
child.stdin
child.stdout
child.stderr

可以在Popen()建立子进程的时候改变标准输入、标准输出和标准错误,并可以利用subprocess.PIPE将多个子进程的输入和输出连接在一起,构成管道(pipe),如下2个例子:

代码如下:
>>> import subprocess
>>> child1 = subprocess.Popen(["ls","-l"], stdout=subprocess.PIPE)
>>> print child1.stdout.read(),
#或者child1.communicate()
>>> import subprocess
>>> child1 = subprocess.Popen(["cat","/etc/passwd"], stdout=subprocess.PIPE)
>>> child2 = subprocess.Popen(["grep","0:0"],stdin=child1.stdout, stdout=subprocess.PIPE)
>>> out = child2.communicate()

subprocess.PIPE实际上为文本流提供一个缓存区。child1的stdout将文本输出到缓存区,随后child2的stdin从该PIPE中将文本读取走。child2的输出文本也被存放在PIPE中,直到communicate()方法从PIPE中读取出PIPE中的文本。
注意:communicate()是Popen对象的一个方法,该方法会阻塞父进程,直到子进程完成

subprocess用来替换多个旧模块和函数:

  • os.system
  • os.spawn*
  • os.popen*
  • popen2.*
  • commands.*

运行python的时候,我们都是在创建并运行一个进程,linux中一个进程可以fork一个子进程,并让这个子进程exec另外一个程序。在python中,我们通过标准库中的subprocess包来fork一个子进程,并且运行一个外部的程序。subprocess包中定义有数个创建子进程的函数,这些函数分别以不同的方式创建子进程,所欲我们可以根据需要来从中选取一个使用。另外subprocess还提供了一些管理标准流(standard stream)和管道(pipe)的工具,从而在进程间使用文本通信。

二、旧有模块的使用

Python subprocess模块功能与常见用法实例详解1.os.system()

执行操作系统的命令,将结果输出到屏幕,只返回命令执行状态(0:成功,非 0 : 失败)

1
2
3
4
5
6
7
8
9
10
11
12
13
import os
>>> a = os.system("df -Th")
Filesystem   Type  Size Used Avail Use% Mounted on
/dev/sda3   ext4  1.8T 436G 1.3T 26% /
tmpfs     tmpfs  16G   0  16G  0% /dev/shm
/dev/sda1   ext4  190M 118M  63M 66% /boot
>>> a
0     # 0 表示执行成功
# 执行错误的命令
>>> res = os.system("list")
sh: list: command not found
>>> res
32512    # 返回非 0 表示执行错误

Python subprocess模块功能与常见用法实例详解2. os.popen()

执行操作系统的命令,会将结果保存在内存当中,可以用read()方法读取出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import os
>>> res = os.popen("ls -l")
# 将结果保存到内存中
>>> print res
<open file="" 'ls="" -l',="" mode="" 'r'="" at="" 0x7f02d249c390="">
# 用read()读取内容
>>> print res.read()
total 267508
-rw-r--r-- 1 root root  260968 Jan 27 2016 AliIM.exe
-rw-------. 1 root root   1047 May 23 2016 anaconda-ks.cfg
-rw-r--r-- 1 root root  9130958 Nov 18 2015 apache-tomcat-8.0.28.tar.gz
-rw-r--r-- 1 root root     0 Oct 31 2016 badblocks.log
drwxr-xr-x 5 root root   4096 Jul 27 2016 certs-build
drwxr-xr-x 2 root root   4096 Jul 5 16:54 Desktop
-rw-r--r-- 1 root root   2462 Apr 20 11:50 Face_24px.ico
 
</open>

三、subprocess模块

Python subprocess模块功能与常见用法实例详解1、subprocess.run()

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> import subprocess
# python 解析则传入命令的每个参数的列表
>>> subprocess.run(["df","-h"])
Filesystem      Size Used Avail Use% Mounted on
/dev/mapper/VolGroup-LogVol00
           289G  70G 204G 26% /
tmpfs         64G   0  64G  0% /dev/shm
/dev/sda1       283M  27M 241M 11% /boot
CompletedProcess(args=['df', '-h'], returncode=0)
# 需要交给Linux shell自己解析,则:传入命令字符串,shell=True
>>> subprocess.run("df -h|grep /dev/sda1",shell=True)
/dev/sda1       283M  27M 241M 11% /boot
CompletedProcess(args='df -h|grep /dev/sda1', returncode=0)

Python subprocess模块功能与常见用法实例详解2、subprocess.call()

执行命令,返回命令的结果和执行状态,0或者非0

1
2
3
4
5
6
7
8
9
10
>>> res = subprocess.call(["ls","-l"])
总用量 28
-rw-r--r-- 1 root root   0 616 10:28 1
drwxr-xr-x 2 root root 4096 622 17:48 _1748
-rw-------. 1 root root 1264 428 20:51 anaconda-ks.cfg
drwxr-xr-x 2 root root 4096 525 14:45 monitor
-rw-r--r-- 1 root root 13160 5月  9 13:36 npm-debug.log
# 命令执行状态
>>> res
0

Python subprocess模块功能与常见用法实例详解3、subprocess.check_call()

执行命令,返回结果和状态,正常为0 ,执行错误则抛出异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
>>> subprocess.check_call(["ls","-l"])
总用量 28
-rw-r--r-- 1 root root   0 616 10:28 1
drwxr-xr-x 2 root root 4096 622 17:48 _1748
-rw-------. 1 root root 1264 428 20:51 anaconda-ks.cfg
drwxr-xr-x 2 root root 4096 525 14:45 monitor
-rw-r--r-- 1 root root 13160 5月  9 13:36 npm-debug.log
0
>>> subprocess.check_call(["lm","-l"])
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 File "/usr/lib64/python2.7/subprocess.py", line 537, in check_call
  retcode = call(*popenargs, **kwargs)
 File "/usr/lib64/python2.7/subprocess.py", line 524, in call
  return Popen(*popenargs, **kwargs).wait()
 File "/usr/lib64/python2.7/subprocess.py", line 711, in __init__
  errread, errwrite)
 File "/usr/lib64/python2.7/subprocess.py", line 1327, in _execute_child
  raise child_exception
OSError: [Errno 2] No such file or directory
 
</module></stdin>

Python subprocess模块功能与常见用法实例详解4、subprocess.getstatusoutput()

接受字符串形式的命令,返回 一个元组形式的结果,第一个元素是命令执行状态,第二个为执行结果

1
2
3
4
5
6
#执行正确
>>> subprocess.getstatusoutput('pwd')
(0, '/root')
#执行错误
>>> subprocess.getstatusoutput('pd')
(127, '/bin/sh: pd: command not found')

Python subprocess模块功能与常见用法实例详解5、subprocess.getoutput()

接受字符串形式的命令,放回执行结果

1
2
>>> subprocess.getoutput('pwd')
'/root'

Python subprocess模块功能与常见用法实例详解6、subprocess.check_output()

执行命令,返回执行的结果,而不是打印

1
2
3
>>> res = subprocess.check_output("pwd")
>>> res
b'/root\n' # 结果以字节形式返回

四、subprocess.Popen()

其实以上subprocess使用的方法,都是对subprocess.Popen的封装,下面我们就来看看这个Popen方法。

Python subprocess模块功能与常见用法实例详解1、stdout

标准输出

1
2
3
4
>>> res = subprocess.Popen("ls /tmp/yum.log", shell=True, stdout=subprocess.PIPE) # 使用管道
>>> res.stdout.read()  # 标准输出
b'/tmp/yum.log\n'
res.stdout.close()  # 关闭

Python subprocess模块功能与常见用法实例详解2、stderr

标准错误

1
2
3
4
5
6
7
8
>>> import subprocess
>>> res = subprocess.Popen("lm -l",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
# 标准输出为空
>>> res.stdout.read()
b''
#标准错误中有错误信息
>>> res.stderr.read()
b'/bin/sh: lm: command not found\n'

注意:上面的提到的标准输出都为啥都需要等于subprocess.PIPE,这个又是啥呢?原来这个是一个管道,这个需要画一个图来解释一下:

Python subprocess模块功能与常见用法实例详解4、poll()

定时检查命令有没有执行完毕,执行完毕后返回执行结果的状态,没有执行完毕返回None

1
2
3
4
5
6
7
>>> res = subprocess.Popen("sleep 10;echo 'hello'",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> print(res.poll())
None
>>> print(res.poll())
None
>>> print(res.poll())
0

Python subprocess模块功能与常见用法实例详解5、wait()

等待命令执行完成,并且返回结果状态

1
2
3
4
>>> obj = subprocess.Popen("sleep 10;echo 'hello'",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> obj.wait()
# 中间会一直等待
0

Python subprocess模块功能与常见用法实例详解6、terminate()

结束进程

1
2
3
4
5
import subprocess
>>> res = subprocess.Popen("sleep 20;echo 'hello'",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> res.terminate() # 结束进程
>>> res.stdout.read()
b''

Python subprocess模块功能与常见用法实例详解7、pid

获取当前执行子shell的程序的进程号

1
2
3
4
import subprocess
>>> res = subprocess.Popen("sleep 5;echo 'hello'",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> res.pid # 获取这个linux shell 的 进程号
2778

python的subprocess模块介绍的更多相关文章

  1. Python中subprocess 模块 创建并运行一个进程

     python的subprocess模块,看到官方声明里说要尽力避免使用shell=True这个参数,于是测试了一下: from subprocess import call import shlex ...

  2. python的subprocess模块(写的不错留作查询)

    python的subprocess模块 subprocess模块是python从2.4版本开始引入的模块.主要用来取代 一些旧的模块方法,如os.system.os.spawn*.os.popen*. ...

  3. python 利用python的subprocess模块执行外部命令,获取返回值

    有时执行dos命令需要保存返回值 需要导入库subprocess import subprocess p = subprocess.Popen('ping www.baidu.com', shell= ...

  4. python之subprocess模块详解--小白博客

    subprocess模块 subprocess是Python 2.4中新增的一个模块,它允许你生成新的进程,连接到它们的 input/output/error 管道,并获取它们的返回(状态)码.这个模 ...

  5. 使用python的subprocess模块调用linux系统命令

    subprocess模块主要有call().check_call().check_output().Popen()函数,简要描述如下: Main API ======== call(...): Run ...

  6. python中subprocess模块

    subprocess  模块 subprocess称之为子进程,进程是一个正在进行的程序 子进程是由另一个正在运行的程序启动的程序,例如QQ聊天点击一个链接,打开了浏览器,那么浏览器称之为QQ的子进程 ...

  7. python的subprocess模块执行shell命令

    subprocess模块可以允许我们执行shell命令 一般来说,使用run()方法就可以满足大部分情况 使用run执行shell命令 In [5]: subprocess.run('echo &qu ...

  8. re模块与subprocess模块介绍

    一:re模块       处理正则表达式的模块,正则表达式就是一些带有特殊含义的符号或者符号的组合. 作用:对字符串进行过滤,在一堆字符串中找到你所关心的内容,你就需要告诉计算机你的过滤的 规则是什么 ...

  9. Python之Subprocess模块

    PS:打开文件时候加b参数是代表以二进制方式打开,在Linux加不加都可以,在windows上面最好加b参数否则可能会出现问题 使用system返回执行结果不赋值,使用popen返回了结果赋值给cmd ...

随机推荐

  1. 【体系结构】有关Oracle SCN知识点的整理

    [体系结构]有关Oracle SCN知识点的整理 1  BLOG文档结构图   BLOG_Oracle_lhr_Oracle SCN的一点研究.pdf 2  前言部分 2.1  导读和注意事项 各位技 ...

  2. json模块中dumps()与dump()区别

    dumps是将dict转化成json字符串格式,loads是将json字符串转化成dict格式. dump和load也是类似的功能,只是与文件操作结合起来了. dump(写入内容,文件对象) 和loa ...

  3. 常用docker管理UI

    1. HumpBacks 特性 Web UI Supporting, Easy to use. Container Grouping and Isolation. Container Upgrades ...

  4. php图片防盗链

    利用.htaccess 重写规则防止图片被盗链 2. 找到httpd.conf 打开重写规则 3.

  5. spring的@Scheduled定时任务,同一时间段的定时任务只会执行一个,其余的会被阻塞,@Scheduled注解定时任务并发执行解决办法,即多线程运行定时任务

    原文:https://blog.csdn.net/qq_35937303/article/details/88851064 现有两个定时任务 @Component("aa") pu ...

  6. C++——STL(算法)

    以下对所有算法进行细致分类并标明功能:<一>查找算法(13个):判断容器中是否包含某个值adjacent_find:   在iterator对标识元素范围内,查找一对相邻重复元素,找到则返 ...

  7. 深度学习Keras框架笔记之核心层基类

    Keras的Layers,就是构成网络的每一层.Keras实现了很多层,包括核心层.卷基层.RNN网络层等诸多常用的网络结构.下面开介绍核心层中包含了哪些内容.因为这个核心层我现在还没有全部用到,所以 ...

  8. myshell

    要求 利用fork,exec,wait编写一个具有执行命令功能的shell

  9. 同步关键词synchronized

    概述 synchronized是java中的一个关键字,也就是说是Java语言内置的特性. synchronized( 一个任意的对象(锁) ){代码块中放操作共享数据的代码. } public sy ...

  10. Hibernate缓存简介和对比、一级缓存、二级缓存详解

    一.hibernate缓存简介 缓存的范围分为3类:  1.事务范围(单Session即一级缓存)     事务范围的缓存只能被当前事务访问,每个事务都有各自的缓存,缓存内的数据通常采用相互关联的对象 ...