Python之subprocess模块

subprocess模块容许你启动一个新的进程,链接输入/输出/错误的管道, 
得到子进程的返回码。这个模块目标是代替一些老的模块,好比os.system和os.spawn. 

python

0x01 常见subprocess方法

subprocess模块中的经常使用函数

函数 描述
subprocess.run() Python 3.5中新增的函数。执行指定的命令,等待命令执行完成后返回一个包含执行结果的CompletedProcess类的实例。
subprocess.call() 执行指定的命令,返回命令执行状态,其功能相似于os.system(cmd)。
subprocess.check_call() Python 2.5中新增的函数。 执行指定的命令,若是执行成功则返回状态码,不然抛出异常。其功能等价于subprocess.run(..., check=True)。
subprocess.check_output() Python 2.7中新增的的函数。执行指定的命令,若是执行状态码为0则返回命令执行结果,不然抛出异常。
subprocess.getoutput(cmd) 接收字符串格式的命令,执行命令并返回执行结果,其功能相似于os.popen(cmd).read()和commands.getoutput(cmd)。
subprocess.getstatusoutput(cmd) 执行cmd命令,返回一个元组(命令执行状态, 命令执行结果输出),其功能相似于commands.getstatusoutput()。

subprocess.run(args*stdin=Noneinput=Nonestdout=Nonestderr=Noneshell=Falsetimeout=Nonecheck=False)

args    该参数用于启动进程。这多是一个列表或一个字符串。
returncode   该参数表示子进程的退出状态。
一般状况下,0做为退出状态代表它成功运行。
负值-N代表子进程被信号N终止(仅POSIX)。
stdout  该参数表示标准输出

此调用方式返回CompletedProcess实例,和直接Popen 差很少,实现是同样的,实际也是调用Popen,与Popen构造函数大体相同,例如:shell

>>> subprocess.run(["ls", "-l"]) # doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)api

>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1数组

>>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0,
stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n')缓存


subprocess.call()

执行由参数提供的命令.
咱们能够用数组做为参数运行命令,也能够用字符串做为参数运行命令(经过设置参数shell=True)
注意,参数shell默认为Falsesession

subprocess.call(['ipconfig','/all'])

subprocess.call('ipconfig /all',shell=True)

 subprocess.getoutput(cmd)

cmd能够直接执行shell命令,而不须要cmd命令以列表输入---subprocess.getoutput("cat /proc/meminfo")
返回值包含cmd的执行结果,能够直接赋值给某个变量
功能和getstatusoutput相似
a=subprocess.getoutput('ipconfig /all')
print(a)

subprocess.getstatusoutput(cmd)

cmd能够直接执行shell命令,而不须要cmd命令以列表输入----subprocess.getstatusoutput("cat /proc/meminfo")函数

返回值包含cmd的执行状态和执行结果,能够直接赋值给某个变量,返回的是一个元组spa

a=subprocess.getstatusoutput('ipconfig /all')
print(a)

 

subprocess.check_call()

check_call基本和call功能同样,只是增长了返回状态码校验,若是执行状态码是0,则返回0,不然抛出异常rest

subprocess.check_call(['ipconfig',  '/all'])

subprocess.check_output()

执行命令,若是状态码是0,则返回执行结果,不然抛出异常--
a=subprocess.check_output(['ipconfig',  '/all'])
print(a)


0x0二、subprocess.Popen()类

该类用于在一个新的进程中执行一个子程序。前面咱们提到过,上面介绍的这些函数都是基于subprocess.Popen类实现的,经过使用这些被封装后的高级函数能够很方面的完成一些常见的需求。因为subprocess模块底层的进程建立和管理是由Popen类来处理的,所以,当咱们没法经过上面哪些高级函数来实现一些不太常见的功能时就能够经过subprocess.Popen类提供的灵活的api来完成。code

1.subprocess.Popen的构造函数

def __init__(self, args, bufsize=-1, executable=None,
                 stdin=None, stdout=None, stderr=None,
                 preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS,
                 shell=False, cwd=None, env=None, universal_newlines=False,
                 startupinfo=None, creationflags=0,
                 restore_signals=True, start_new_session=False,
                 pass_fds=(), *, encoding=None, errors=None)
参数说明:
  • args: 要执行的shell命令,能够是字符串,也能够是命令各个参数组成的序列。当该参数的值是一个字符串时,该命令的解释过程是与平台相关的,所以一般建议将args参数做为一个序列传递。
  • bufsize: 指定缓存策略,0表示不缓冲,1表示行缓冲,其余大于1的数字表示缓冲区大小,负数 表示使用系统默认缓冲策略。
  • stdin, stdout, stderr: 分别表示程序标准输入、输出、错误句柄。
  • preexec_fn: 用于指定一个将在子进程运行以前被调用的可执行对象,只在Unix平台下有效。
  • close_fds: 若是该参数的值为True,则除了0,1和2以外的全部文件描述符都将会在子进程执行以前被关闭。
  • shell: 该参数用于标识是否使用shell做为要执行的程序,若是shell值为True,则建议将args参数做为一个字符串传递而不要做为一个序列传递。
  • cwd: 若是该参数值不是None,则该函数将会在执行这个子进程以前改变当前工做目录。
  • env: 用于指定子进程的环境变量,若是env=None,那么子进程的环境变量将从父进程中继承。若是env!=None,它的值必须是一个映射对象。
  • universal_newlines: 若是该参数值为True,则该文件对象的stdin,stdout和stderr将会做为文本流被打开,不然他们将会被做为二进制流被打开。
  • startupinfo和creationflags: 这两个参数只在Windows下有效,它们将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如主窗口的外观,进程优先级等。

 

2. subprocess.Popen类的实例可调用的方法

方法 描述
Popen.poll() 用于检查子进程(命令)是否已经执行结束,没结束返回None,结束后返回状态码。
Popen.wait(timeout=None) 等待子进程结束,并返回状态码;若是在timeout指定的秒数以后进程尚未结束,将会抛出一个TimeoutExpired异常。
Popen.communicate(input=None, timeout=None) 该方法可用来与进程进行交互,好比发送数据到stdin,从stdout和stderr读取数据,直到到达文件末尾。
Popen.send_signal(signal) 发送指定的信号给这个子进程。
Popen.terminate() 中止该子进程。
Popen.kill() 杀死该子进程。

关于communicate()方法的说明:

  • 该方法中的可选参数 input 应该是将被发送给子进程的数据,或者如没有数据发送给子进程,该参数应该是None。input参数的数据类型必须是字节串,若是universal_newlines参数值为True,则input参数的数据类型必须是字符串。
  • 该方法返回一个元组(stdout_data, stderr_data),这些数据将会是字节穿或字符串(若是universal_newlines的值为True)。
  • 若是在timeout指定的秒数后该进程尚未结束,将会抛出一个TimeoutExpired异常。捕获这个异常,而后从新尝试通讯不会丢失任何输出的数据。可是超时以后子进程并无被杀死,为了合理的清除相应的内容,一个好的应用应该手动杀死这个子进程来结束通讯。
  • 须要注意的是,这里读取的数据是缓冲在内存中的,因此,若是数据大小很是大或者是无限的,就不该该使用这个方法。

3. subprocess.Popen使用实例

实例1:

>>> import subprocess
>>>
>>> p = subprocess.Popen('df -Th', stdout=subprocess.PIPE, shell=True)
>>> print(p.stdout.read())
Filesystem     Type      Size  Used Avail Use% Mounted on
/dev/vda1      ext4       40G   12G   26G  31% /
devtmpfs       devtmpfs  3.9G     0  3.9G   0% /dev
tmpfs          tmpfs     3.9G     0  3.9G   0% /dev/shm
tmpfs          tmpfs     3.9G  386M  3.5G  10% /run
tmpfs          tmpfs     3.9G     0  3.9G   0% /sys/fs/cgroup
tmpfs          tmpfs     783M     0  783M   0% /run/user/0
tmpfs          tmpfs     783M     0  783M   0% /run/user/1000

实例2:

>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> obj.stdin.write('print(1) \n')
>>> obj.stdin.write('print(2) \n')
>>> obj.stdin.write('print(3) \n')
>>> out,err = obj.communicate()
>>> print(out)
1
2
3

>>> print(err)

实例3:

>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> out,err = obj.communicate(input='print(1) \n')
>>> print(out)
1

>>> print(err)

 

实例4:

实现相似df -Th | grep data命令的功能,实际上就是实现shell中管道的共功能。

>>> 
>>> p1 = subprocess.Popen(['df', '-Th'], stdout=subprocess.PIPE)
>>> p2 = subprocess.Popen(['grep', 'data'], stdin=p1.stdout, stdout=subprocess.PIPE)
>>> out,err = p2.communicate()
>>> print(out)
/dev/vdb1      ext4      493G  4.8G  463G   2% /data
/dev/vdd1      ext4     1008G  420G  537G  44% /data1
/dev/vde1      ext4      985G  503G  432G  54% /data2

>>> print(err)
None
 
相关文章
相关标签/搜索