zoukankan      html  css  js  c++  java
  • 【转】 Python subprocess模块学习总结

    从Python 2.4开始,Python引入subprocess模块来管理子进程,以取代一些旧模块的方法:如 os.system、os.spawn*、os.popen*、popen2.*、commands.*不但可以调用外部的命令作为子进程,而且可以连接到子进程的input/output/error管道,获取相关的返回信息
     
     

    一、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('ping www.baidu.com')
    print retcode
    

    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)
    
    args 字符串或者列表
    bufsize 0 无缓冲
    1 行缓冲
    其他正值 缓冲区大小
    负值 采用默认系统缓冲(一般是全缓冲)
    executable 一般不用,args字符串或列表第一项表示程序名
    stdin
    stdout
    stderr
    None 没有任何重定向,继承父进程
    PIPE 创建管道
    文件对象
    文件描述符(整数)
    stderr 还可以设置为 STDOUT
    preexec_fn 钩子函数, 在fork和exec之间执行。(unix)
    close_fds unix 下执行新进程前是否关闭0/1/2之外的文件
    windows下不继承还是继承父进程的文件描述符
    shell 为真的话
    unix下相当于args前面添加了 "/bin/sh“ ”-c”
    window下,相当于添加"cmd.exe /c"
    cwd 设置工作目录
    env 设置环境变量
    universal_newlines 各种换行符统一处理成 ' '
    startupinfo window下传递给CreateProcess的结构体
    creationflags

    windows下,传递CREATE_NEW_CONSOLE创建自己的控制台窗口

    creationflags=0x08000000        #测试过程中不显示shell window

    其中的args 参数,可以是一个字符串,可以是一个列表。

    • UNIX下
    subprocess.Popen(["gedit","abc.txt"])
    subprocess.Popen("gedit abc.txt")
    

    这两个之中,后者将不会工作。因为如果是一个字符串的话,必须是程序的路径才可以。(考虑unix的api函数 exec,接受的是字符串列表)

    但是下面的可以工作

    subprocess.Popen("gedit abc.txt", shell=True)
    

    这是因为它相当于  

    subprocess.Popen(["/bin/sh", "-c", "gedit abc.txt"])
    
    • Windows下
    subprocess.Popen(["notepad.exe", "abc.txt"])
    subprocess.Popen("notepad.exe abc.txt")
    

    这是由于windows下的api函数CreateProcess接受的是一个字符串。即使是列表形式的参数,也需要先合并成字符串再传递给api函数。  

    类似上面

    subprocess.Popen("notepad.exe abc.txt",shell=True)
    

    等价于  

    subprocess.Popen("cmd.exe /C "+"notepad.exe abc.txt",shell=True)
    

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

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

    import subprocess
    child = subprocess.Popen('ping www.baidu.com')
    child.wait()
    print 'parent process'
    

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

    child.poll() # 检查子进程状态 结果PASS,返回0;Fail,返回1;运行中时无值
    child.kill() # 终止子进程
    child.send_signal() # 向子进程发送信号
    child.terminate() # 终止子进程
    child.pid() #子进程PID

      

    二、子进程的文本流控制

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

    child.stdin
    child.stdout
    child.stderr
    

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

    import subprocess
    child1 = subprocess.Popen(’ping www.baidu.com‘, stdout=subprocess.PIPE)
    print child1.stdout.read()
    #或者child1.communicate()
    

    结果如下:

    正在 Ping www.a.shifen.com [180.97.33.108] 具有 32 字节的数据:
    
    来自 180.97.33.108 的回复: 字节=32 时间=8ms TTL=54
    
    来自 180.97.33.108 的回复: 字节=32 时间=7ms TTL=54
    
    来自 180.97.33.108 的回复: 字节=32 时间=9ms TTL=54
    
    来自 180.97.33.108 的回复: 字节=32 时间=7ms TTL=54
    
    
    
    180.97.33.108 的 Ping 统计信息:
    
        数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
    
    往返行程的估计时间(以毫秒为单位):
    
        最短 = 7ms,最长 = 9ms,平均 = 7ms
    

      

      

      

      

      

      

  • 相关阅读:
    SqlConnectionStringBuilder
    什么时候使用“静态方法”(转)
    Dos命令下多文件中查找某字符串
    StructLayout(LayoutKind.Sequential)(转)
    DOS批处理高级教程:第四章 批处理中的变量(转)
    DOS批处理高级教程:第一章 批处理基础(转)
    C#各种进制之间数据转换二进制、八进制、十进制、十六进制
    DOS批处理高级教程:第六章 if命令讲解(转)
    ModbusRTU模式和结束符(转)
    DOS批处理高级教程:第七章 DOS批处理编程高级技巧(转)
  • 原文地址:https://www.cnblogs.com/hester/p/4866290.html
Copyright © 2011-2022 走看看