zoukankan      html  css  js  c++  java
  • 【Python基础到进阶】subprocess模块

    subprocess模块

    subprocess 到底是用来干什么的?

    subprocess 允许你去创建一个新的进程让其执行另外的程序,并与它进行通信,获取标准的输入、标准输出、标准错误以及返回码等。

    在Windows上也可以使用os.system()这个函数来执行一些dos命令,但是这个命令只能拿到返回码,拿不到标准输出,标准错误,所以通常使用的subprocess模块中的Popen类来实现。

    我们能从Python官方文档里读到应该用subprocess 模块来运行系统命令,subprocess模块允许我们创建子进程,连接他们的输入/输出/错误管道,还有获得返回值。
    subprocess模块打算来替代几个过时的模块和函数,比如:os.system, os.spawn*, os.popen*, popen2.*命令。

    Popen类

    subprocess模块中定义了一个Popen类,通过它可以来创建进程,并与其进行复杂的交互。查看一下它的构造函数:

    __init__(self, 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)

    主要参数说明: 

    args:args should be a string, or a sequence of program arguments.也就是说必须是一个字符串或者序列类型(如:字符串、list、元组),用于指定进程的可执行文件及其参数。如果是一个序列类型参数,则序列的第一个元素通常都必须是一个可执行文件的路径。当然也可以使用executeable参数来指定可执行文件的路径。
    
    stdin,stdout,stderr:分别表示程序的标准输入、标准输出、标准错误。有效的值可以是PIPE,存在的文件描述符,存在的文件对象或None,如果为None需从父进程继承过来,stdout可以是PIPE,表示对子进程创建一个管道,stderr可以是STDOUT,表示标准错误数据应该从应用程序中捕获并作为标准输出流stdout的文件句柄。
    
    shell:如果这个参数被设置为True,程序将通过shell来执行。 
    
    env:它描述的是子进程的环境变量。如果为None,子进程的环境变量将从父进程继承而来。

    创建Popen类的实例对象

    res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stdin = subprocess.PIPE ,stderr=subprocess.PIPE)

    cmd:标准像子进程传入需要执行的shell命令,如:ls -al ‘dir’

    subprocess.PIPE:在创建Popen对象时,subprocess.PIPE可以初始化为stdin, stdout或stderr的参数,表示与子进程通信的标准输入流,标准输出流以及标准错误。

    subprocess.STDOUT:可以作为Popen对象的stderr的参数,表示将标准错误通过标准输出流输出。

    一些常用的Popen方法和属性

    import subprocess
    res=subprocess.Popen('dir',shell=True,stdout=subprocess.PIPE,stdin=subprocess.PIPE,stderr=subprocess.PIPE)
    res.stdout.read()

    再一次读取管道的结果 res 为空

    >>> res.stdout.read()
    b''

    输入错误的cmd

    >>> res=subprocess.Popen('23154nkdaslafsd',shell=True,stdout=subprocess.PIPE,stdin=subprocess.PIPE,stderr=subprocess.PIPE)
    >>> res.stdout.read()
    b''
    >>> res.stderr.read()
    b"'23154nkdaslafsd' xb2xbbxcaxc7xc4xdaxb2xbfxbbxf2xcdxe2xb2xbfxc3xfcxc1xeexa3xacxd2xb2xb2xbbxcaxc7xbfxc9xd4xcbxd0xd0xb5xc4xb3xccxd0xf2
    xbbxf2xc5xfaxb4xa6xc0xedxcexc4xbcxfexa1xa3
    "

    Popen类拥有的方法及属性

    1、Popen.pid 

    获取子进程的进程ID。

    2、Popen.returncode 

    获取进程的返回码。如果进程未结束,将返回None。

    3、communicate(input=None) 

    与子进程进行交互,像stdin发送数据,并从stdout和stderr读出数据存在一个tuple中并返回。 参数input应该是一个发送给子进程的字符串,如果未指定数据,将传入None。

    4、poll() 

    检查子进程是否结束,并返回returncode属性。

    5、wait()

    Wait for child process to terminate. Returns returncode attribute.(等待子进程执行结束,并返回returncode属性,如果为0表示执行成功。)

    6、send_signal( sig)

    Send a signal to the process(发送信号给子进程。)

    7、terminate()

    Terminates the process(终止子进程。windows下将调用Windows API TerminateProcess()来结束子进程。)

    8、kill() 

    官方文档对这个函数的解释跟terminate()是一样的,表示杀死子进程。

    进程通信实例1

    打开一个只有ip地址的文本文件,读取其中的ip,然后进行ping操作,并将ping结果写入ping.txt文件中。 
    首先创建一个子进程res,传入要执行的shell命令,并获得标准输出流、返回码等。

    import subprocess
    
    class Shell(object):
        def runCmd(self, cmd):
            res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
            sout, serr = res.communicate()
            # print(res.returncode, sout, serr, res.pid)
            return res.returncode, sout, serr, res.pid
    
    shell = Shell()
    fp = open('ip.txt', 'r',encoding='utf8')
    ipList = fp.readlines()
    fp.close()
    fp = open('ping.txt', 'w',encoding='utf8')
    print(ipList)
    for i in ipList:
        i = i.strip()
        result = shell.runCmd('ping ' + i)
        if result[0] == 0:      #没有ping 到结果
            w = i + ' : ping到结果了'
            print(result)
            fp.write(w + '
    ')
    
        else:           ##ping 到结果了
            w = i + ' : ping失败'
            print(result)
            fp.write(w + '
    ')
    
    fp.close()

    返回结果:

    ['www.baidu.com
    ', 'www.taobao.com
    ', 'www.cnblogs.com
    ', 'www.jioghidgjnia.com']
    (0, b'
    xd5xfdxd4xda Ping www.baidu.com [183.232.231.174] xbexdfxd3xd0 32 xd7xd6xbdxdaxb5xc4xcaxfdxbexdd:
    xc0xb4xd7xd4 183.232.231.174 xb5xc4xbbxd8xb8xb4: xd7xd6xbdxda=32 xcaxb1xbcxe4=35ms TTL=54
    xc0xb4xd7xd4 183.232.231.174 xb5xc4xbbxd8xb8xb4: xd7xd6xbdxda=32 xcaxb1xbcxe4=36ms TTL=54
    xc0xb4xd7xd4 183.232.231.174 xb5xc4xbbxd8xb8xb4: xd7xd6xbdxda=32 xcaxb1xbcxe4=44ms TTL=54
    xc0xb4xd7xd4 183.232.231.174 xb5xc4xbbxd8xb8xb4: xd7xd6xbdxda=32 xcaxb1xbcxe4=68ms TTL=54
    
    183.232.231.174 xb5xc4 Ping xcdxb3xbcxc6xd0xc5xcfxa2:
        xcaxfdxbexddxb0xfc: xd2xd1xb7xa2xcbxcd = 4xa3xacxd2xd1xbdxd3xcaxd5 = 4xa3xacxb6xaaxcaxa7 = 0 (0% xb6xaaxcaxa7)xa3xac
    xcdxf9xb7xb5xd0xd0xb3xccxb5xc4xb9xc0xbcxc6xcaxb1xbcxe4(xd2xd4xbaxc1xc3xebxcexaaxb5xa5xcexbb):
        xd7xeexb6xcc = 35msxa3xacxd7xeexb3xa4 = 68msxa3xacxc6xbdxbexf9 = 45ms
    ', None, 9948)
    (0, b'
    xd5xfdxd4xda Ping www.taobao.com [223.99.232.254] xbexdfxd3xd0 32 xd7xd6xbdxdaxb5xc4xcaxfdxbexdd:
    xc0xb4xd7xd4 223.99.232.254 xb5xc4xbbxd8xb8xb4: xd7xd6xbdxda=32 xcaxb1xbcxe4=39ms TTL=53
    xc0xb4xd7xd4 223.99.232.254 xb5xc4xbbxd8xb8xb4: xd7xd6xbdxda=32 xcaxb1xbcxe4=27ms TTL=53
    xc0xb4xd7xd4 223.99.232.254 xb5xc4xbbxd8xb8xb4: xd7xd6xbdxda=32 xcaxb1xbcxe4=27ms TTL=53
    xc0xb4xd7xd4 223.99.232.254 xb5xc4xbbxd8xb8xb4: xd7xd6xbdxda=32 xcaxb1xbcxe4=59ms TTL=53
    
    223.99.232.254 xb5xc4 Ping xcdxb3xbcxc6xd0xc5xcfxa2:
        xcaxfdxbexddxb0xfc: xd2xd1xb7xa2xcbxcd = 4xa3xacxd2xd1xbdxd3xcaxd5 = 4xa3xacxb6xaaxcaxa7 = 0 (0% xb6xaaxcaxa7)xa3xac
    xcdxf9xb7xb5xd0xd0xb3xccxb5xc4xb9xc0xbcxc6xcaxb1xbcxe4(xd2xd4xbaxc1xc3xebxcexaaxb5xa5xcexbb):
        xd7xeexb6xcc = 27msxa3xacxd7xeexb3xa4 = 59msxa3xacxc6xbdxbexf9 = 38ms
    ', None, 1084)
    (0, b'
    xd5xfdxd4xda Ping www.cnblogs.com [42.121.252.58] xbexdfxd3xd0 32 xd7xd6xbdxdaxb5xc4xcaxfdxbexdd:
    xc0xb4xd7xd4 42.121.252.58 xb5xc4xbbxd8xb8xb4: xd7xd6xbdxda=32 xcaxb1xbcxe4=8ms TTL=91
    xc0xb4xd7xd4 42.121.252.58 xb5xc4xbbxd8xb8xb4: xd7xd6xbdxda=32 xcaxb1xbcxe4=25ms TTL=91
    xc0xb4xd7xd4 42.121.252.58 xb5xc4xbbxd8xb8xb4: xd7xd6xbdxda=32 xcaxb1xbcxe4=19ms TTL=91
    xc0xb4xd7xd4 42.121.252.58 xb5xc4xbbxd8xb8xb4: xd7xd6xbdxda=32 xcaxb1xbcxe4=10ms TTL=91
    
    42.121.252.58 xb5xc4 Ping xcdxb3xbcxc6xd0xc5xcfxa2:
        xcaxfdxbexddxb0xfc: xd2xd1xb7xa2xcbxcd = 4xa3xacxd2xd1xbdxd3xcaxd5 = 4xa3xacxb6xaaxcaxa7 = 0 (0% xb6xaaxcaxa7)xa3xac
    xcdxf9xb7xb5xd0xd0xb3xccxb5xc4xb9xc0xbcxc6xcaxb1xbcxe4(xd2xd4xbaxc1xc3xebxcexaaxb5xa5xcexbb):
        xd7xeexb6xcc = 8msxa3xacxd7xeexb3xa4 = 25msxa3xacxc6xbdxbexf9 = 15ms
    ', None, 9720)
    (1, b'Ping xc7xebxc7xf3xd5xd2xb2xbbxb5xbdxd6xf7xbbxfa www.jioghidgjnia.comxa1xa3xc7xebxbcxecxb2xe9xb8xc3xc3xfbxb3xc6xa3xacxc8xbbxbaxf3xd6xd8xcaxd4xa1xa3
    ', None, 2492)
    View Code

     

    进程通信实例2

    命令交互,不断从键盘接受命令执行,给出执行结果,直到用户输入exit或者bye退出命令交互。

    import subprocess
    class Shell(object):
        def runCmd(self, cmd):
            res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
            sout, serr = res.communicate()
            return res.returncode, sout, serr, res.pid
    
    shell = Shell()
    while True:
        inp = input('>>>')
        if inp == 'exit' or inp == 'bye':
            break
        else:
            result = shell.runCmd(inp)
            print("返回码:", result[0])
            print("标准输出:", result[1].decode('gbk'))
            print("标准错误:", result[2])

    输出结果:

    >>>dir
    返回码: 0
    标准输出:  驱动器 D 中的卷是 DATA
     卷的序列号是 C2A2-1B5C
    
     D:360DownloadsPython编程老男孩Python全栈Python基础到进阶Python模块subprocess模块 的目录
    
    2019/05/23 周四  09:33    <DIR>          .
    2019/05/23 周四  09:33    <DIR>          ..
    2019/05/23 周四  09:22                68 ip.txt
    2019/05/23 周四  09:27               140 ping.txt
    2019/05/23 周四  09:28               832 进程通信实例1.py
    2019/05/23 周四  09:33               563 进程通信实例2.py
                   4 个文件          1,603 字节
                   2 个目录 112,898,076,672 可用字节
    
    标准错误: None
    >>>
  • 相关阅读:
    Django使用manage.py test错误解决
    Notepad++的find result窗口恢复
    qrcode 配套 PIL 或者 Image + ImageDraw
    pymssql.OperationalError: (20017 问题解决
    ConfigParser使用:1.获取所有section为list,2.指定section具体值,并转换为dict
    selenium&Firefox不兼容问题:Message: Unable to find a matching set of capabilitie;Can't load the profile. Profile;Message: 'geckodriver' executable needs to be in PATH
    使用宏实现透视表部分功能,将AB列数据合并统计.
    反射
    类的多态
    封装
  • 原文地址:https://www.cnblogs.com/XJT2018/p/10910039.html
Copyright © 2011-2022 走看看