zoukankan      html  css  js  c++  java
  • python subprocess模块

    python模块系列之 - subprocess

    subprocess – 创建附加进程 
    subprocess模块提供了一种一致的方法来创建和处理附加进程,与标准库中的其它模块相比,提供了一个更高级的接口。用于替换如下模块: 
    os.system() , os.spawnv() , os和popen2模块中的popen()函数,以及 commands().

    1、subprocess.call()

    subprocess的call方法可以用于执行一个外部命令,但该方法不能返回执行的结果,只能返回执行的状态码: 成功(0) 或 错误(非0) 

    import subprocess
    
    ret = subprocess.call(["", "-h"])
    print(ret)
    ret = subprocess.call("df -h", shell=true)
    print(ret)
    #!/usr/bin/python
    #! -*- coding:utf-8 -*-
    import subprocess
    
    ret = subprocess.call(["df", "-h"])
    print(ret)
    ret = subprocess.call("df -h", shell=True)
    print(ret)
    运行结果

    如上实例所示,虽然我们能看到执行的结果,但实际获取的值只是状态码

    2、subprocess.check_call() 方法 

    check_call与call命令相同,区别是如果出错会报错

    我们说过call执行返回一个状态码,我们可以通过check_call()函数来检测命令的执行结果,如果出现错误,进行报错【如果returncode不为0,则举出错误subprocess.CalledProcessError,该对象包含有returncode属性,可用try…except…来检查

    import subprocess
    
    ret = subprocess.check_call(["dd", "-h"])  # dd -h ,命令不存在
    print(ret)
    Traceback (most recent call last):
      File "1.py", line 5, in <module>
        ret = subprocess.check_call(["dd", "-h"])
      File "/usr/local/python3/lib/python3.5/subprocess.py", line 271, in check_call
        raise CalledProcessError(retcode, cmd)
    subprocess.CalledProcessError: Command '['dd', '-h']' returned non-zero exit status 1
    运行结果

    使用try...excepe...来捕获异常

    import subprocess
    
    try:
        ret = subprocess.check_call("etstat -tn", shell = True)
    except subprocess.CalledProcessError:
        print("error")
    else:
        print(ret)
    [root@ming python]# python 2.py 
    /bin/sh: etstat: command not found
    error
    运行结果

    3、subprocess.check_output()方法

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

    import subprocess
    
    try:
        ret = subprocess.check_output("netstat -tn", shell = True)  #可以执行成功
    except subprocess.CalledProcessError:
        print("error")
    else:
        print(ret.decode('GBK')) # 输出执行结果
    活动连接
    
      协议  本地地址          外部地址        状态           卸载状态
    
      TCP    127.0.0.1:443          127.0.0.1:54149        ESTABLISHED     InHost      
      TCP    127.0.0.1:443          127.0.0.1:57952        ESTABLISHED     InHost      
      TCP    127.0.0.1:8307         127.0.0.1:54150        ESTABLISHED     InHost      
      TCP    127.0.0.1:8307         127.0.0.1:57957        ESTABLISHED     InHost      
      TCP    127.0.0.1:54149        127.0.0.1:443          ESTABLISHED     InHost      
      TCP    127.0.0.1:54150        127.0.0.1:8307         ESTABLISHED     InHost      
    运行结果
    import subprocess
    
    try:
        ret = subprocess.check_output("nestat -tn", shell = True)   #命令错误
    except subprocess.CalledProcessError:
        print("error")
    else:
        print(ret.decode('GBK')) # 输出执行结果
    'nestat' 不是内部或外部命令,也不是可运行的程序
    或批处理文件。
    error
    运行结果

     4、subprocess.Popen()方法

    实际上,subprocess模块中只定义了一个类: Popen。上面的几个函数都是基于Popen()的封装(wrapper)。从Python2.4开始使用Popen来创建进程,用于连接到子进程的标准输入/输出/错误中去,还可以得到子进程的返回值。这些封装的目的在于让我们容易使用子进程。当我们想要更个性化我们的需求的时候,就要转向Popen类,该类生成的对象用来代表子进程。

    构造函数如下:

    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)

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

    a、父进程不等待子进程

    import subprocess
    
    child = subprocess.Popen('ping www.baidu.com', shell= True)
    print("hello")  
    [root@ming python]# python 3.py 
    hello
    PING www.a.shifen.com (220.181.112.244) 56(84) bytes of data.
    64 bytes from 220.181.112.244: icmp_seq=1 ttl=57 time=1.93 ms
    64 bytes from 220.181.112.244: icmp_seq=2 ttl=57 time=3.28 ms
    64 bytes from 220.181.112.244: icmp_seq=3 ttl=57 time=3.62 ms
    64 bytes from 220.181.112.244: icmp_seq=4 ttl=57 time=1.45 ms
    64 bytes from 220.181.112.244: icmp_seq=5 ttl=57 time=1.46 ms
    运行结果

    可以看出,Python并没有等到child子进程执行的Popen操作完成就执行了print操作。

    b、添加子进程等待

    import subprocess
    
    child = subprocess.Popen('ping -c 4 www.baidu.com', shell= True)
    child.wait()    #子进程等待
    print("hello")
    [root@ming python]# python 3.py 
    PING www.a.shifen.com (220.181.111.188) 56(84) bytes of data.
    64 bytes from 220.181.111.188: icmp_seq=1 ttl=59 time=2.01 ms
    64 bytes from 220.181.111.188: icmp_seq=2 ttl=59 time=2.28 ms
    64 bytes from 220.181.111.188: icmp_seq=3 ttl=59 time=8.70 ms
    64 bytes from 220.181.111.188: icmp_seq=4 ttl=59 time=1.82 ms
    --- www.a.shifen.com ping statistics ---
    4 packets transmitted, 4 received, 0% packet loss, time 3041ms
    rtt min/avg/max/mdev = 1.824/3.707/8.701/2.888 ms
    hello
    运行结果

    可以看出,print语句是等待child子进程执行完后才执行的

    此外,你还可以在父进程中对子进程进行其它操作,比如我们上面例子中的child对象:

    child.poll() # 检查子进程状态
    child.kill() # 终止子进程
    child.send_signal() # 向子进程发送信号
    child.terminate() # 终止子进程
    ps: 子进程的PID存储在child.pid

    c、子进程文本流控制

    子进程的标准输入、标准输出和标准错误如下属性分别表示:

    child.stdin | child.stdout | child.stderr

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

    例=1
    #
    !/usr/bin/env python import subprocess child = subprocess.Popen(['ls','-l'],stdout=subprocess.PIPE)#将标准输出定向输出到subprocess.PIPE print(child.stdout.read().decode("UTF-8")) #使用 child.communicate() 输出的是一个元组
    运行结果
    [root@ming python]# python 5.py total 20 -rw-r--r--. 1 root root 176 Dec 5 00:50 1.py -rw-r--r--. 1 root root 210 Dec 5 01:03 2.py -rw-r--r--. 1 root root 108 Dec 5 01:47 3.py -rw-r--r--. 1 root root 178 Dec 6 20:39 4.py -rw-r--r--. 1 root root 194 Dec 6 21:52 5.py
    例=2
    #
    !/usr/bin/env python import subprocess child1 = subprocess.Popen(['cat','/etc/passwd'],stdout=subprocess.PIPE) child2 = subprocess.Popen(['grep','root'],stdin=child1.stdout,stdout=subprocess.PIPE) a = child2.communicate() #是一个元组 for i in a: if i: print(i.decode("UTF-8"))
    运行结果
    [root@ming python]# python 6.py 
    root:x:0:0:root:/root:/bin/bash
    operator:x:11:0:operator:/root:/sbin/nologin

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

  • 相关阅读:
    Post请求的两种编码格式:application/x-www-form-urlencoded和multipart/form-data传参方式
    工作中常用的JavaScript函数片段
    解决导入导出Excel表格文字乱码问题
    清空antd-design时间选择组件 RangePicker的值
    react.js Hooks路由跳转
    linux跳板机服务器搭建
    docker及docker-compose学习
    Android Jenkins+Git+Gradle持续集成
    Windows Server 2008 R2常规安全设置及基本安全策略
    ubuntu lnmp安装及php扩展
  • 原文地址:https://www.cnblogs.com/ming5218/p/7976453.html
Copyright © 2011-2022 走看看