zoukankan      html  css  js  c++  java
  • 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:Codepycharm文件存放处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
    '
    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
    '
     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!
    /root
    '
     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
    '
    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
    '
    4 >>> 
    5 ‘’‘
    6 提示:
    7 env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。
    8 ’‘’

     

  • 相关阅读:
    ubuntu升级显卡驱动
    __slots__属性,声明实力属性名字列表
    isinstance 与 type 的区别
    conda使用技巧
    卷积神经网络参数
    apache nginx php不显示版本号
    30个实用的Linux find命令示例
    账号的管理的那点事
    Linux 命令整理 —— 基本操作
    Linux 命令整理 —— 用户管理
  • 原文地址:https://www.cnblogs.com/yinzhengjie/p/8576673.html
Copyright © 2011-2022 走看看