zoukankan      html  css  js  c++  java
  • 子进程管理模块subprocess

            subprocess模块允许你生成子进程,连接管道,并获取返回的代码。

            一.使用subprocess模块

            模块中定义了一个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)

            参数如下:

            args:应该是一个字符串,或者一连串命令参数,要运行的程序通常是是args的第一个元素,但是也可以通过executable来显示声明。如果显示声明了args,参数序列的第一个元素依然被大多数程序作为命令名。

    1. >>>import shlex, subprocess
    2. >>> command_line = raw_input()
    3. /bin/vikings -input eggs.txt -output "spam spam.txt"-cmd "echo '$MONEY'"
    4. >>> args = shlex.split(command_line)
    5. >>>print args
    6. ['/bin/vikings','-input','eggs.txt','-output','spam spam.txt','-cmd',"echo '$MONEY'"]
    7. >>> p = subprocess.Popen(args)# Success!

            在Unix中,如果shell=false(默认情况下),那么Popen使用os.execvp()来执行子程序,args应该是参数序列。如果shell=true,如果args是字符串,那么这个字符串必须跟在命令行中输入的字符串一样;如果是参数序列,第一个元素指定为命令行字符串,剩下的元素就被视为参数,也就是说,相当于以下的命令。

    1. Popen(['/bin/sh','-c', args[0], args[1],...])

            而在Window中,Popen使用CreateProcess()来执行子程序,传递的args为字符串,如果arg是参数序列,将会自动调用list2cmdline()转化成字符串。

            bufsize:0意味着无缓存(默认值),1意味着行缓存,其他正整数意味着使用这个整数大小作为缓存大小。负整数意味着使用系统默认的值,通常意味着全缓存。

            executable:指定要执行的程序,一般不需要。

            stdin、stdout、stderr:指定程序的标准输出,标准输入,标准错误输出。可能值为管道或者文件描述符,文件对象,或者None。stderr可以为STDOUT,意思是错误信息页通过标准输出输出。

            preexec_fn:可调用对象,在程序执行前调用,只有Unix下可用。

            close_fds:如果为True,所有的文件描述符(除了0,1,2)在子进程运行前都得关闭。(只有Unix下可用)。

            shell:如果为True,指定的命令将通过shell来执行。

            cwd:如果不是None,那么子进程当前的目录在执行前会切换到cwd,注意当搜索可执行文件的时候不是根据这个目录来查找的,所以不能针对这个目录来指定相对路径。

            env:如果非None,必须是一个映射,定义了针对这个子进程的环境变量。

            univerval_newline:如果为True,则所有平台使用通用的换行符' '。

            startupinfo、creationflag:仅针对windows有效。

            subprocess.PIPE:可以传递给stdin、stdout、stderr的特殊值。

            subprocess.STDOUT可以传递给stderr,表示错误信息通过stdout输出。

            1.实用方法

            模块提供了两个实用方法。

            subprocess.call(*popenargs, **kwargs)

            使用给定参数运行命令,等待命令执行完,然后返回返回码。给定的参数跟Popen的参数一样。例如  

    1. >>> retcode = subprocess.call(["ls","-l"])

            subprocess.check_call(*popenargs, **kwargs)

            使用给定参数运行命令,等待命令执行完,如果返回码为0,则返回它,如果非0,则将抛出CalledProcessError,这个对象里面有returncode属性。需要的参数跟Popen的一样。例如 

    1. >>> subprocess.check_call(["ls","-l"])
    2. 0
            subprocess.check_output(*popenargs, **kwargs)
            运行命令并返回结果,结果为字符串形式。如果返回码非0,将抛出CalledProcessError异常,需要的参数跟Popen一样。
    1. >>> subprocess.check_output(["ls","-l","/dev/null"])
    2. 'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null '
            如果想捕获异常信息,可以使用stderr=subprocess.STDOUT。
    1. >>> subprocess.check_output(
    2. ...["/bin/sh","-c","ls non_existent_file; exit 0"],
    3. ... stderr=subprocess.STDOUT)
    4. 'ls: non_existent_file: No such file or directory '

            2.异常

            异常在子进程中抛出,异常还有一个格外的属性,child_traceback。最常见的异常是OSError。例如执行一个不存在的文件。当Popen使用一个非法的参数时,抛出ValueError异常,check_output()会抛出CalledProcessError。

            二、Popen对象

            Popen对象有如下方法。

            Popen.poll() :检查子进程是否被中断,设置并返回返回码。

            Popen.wait():等待子程序运行完,设置并返回返回码。

            Popen.communicate(input=None):与子进程进行通信。输入信息到stdin,从stdout和stderr中读取信息。知道文件末尾。等待进程执行完,可选参数是个字符串,是输入给子进程的信息,如果为None,则意味着不需要发送信息给子进程。这个方法返回一个元组(stdoutdata, stderrdata),注意,如果你想发送信息给子进程,必须在创建Popen的时候使用stdin=PIPE,同样,如果想从stdout和stderr中获取信息,也需要设置它们为PIPE。

            Popen.send_signal(signal):给子进程发送信号。

            Popen.terminate():终止子进程

            Popen.kill():杀死子进程。

            Popen.stdin:子进程的标准输入

            Popen.stdout:子进程的标准输出。

            Popen.stderr:子进程的标准错误输出。

            Popen.pid:子进程的ID。

            Popen.returncode:子进程的返回码

            三、示例。

            通过subprocess,可以在python中间接的执行shell命令。以下例子均假设已经运行了from subprocess import * 命令。

            例1:间接执行反引号语句

    1. output=`mycmd myarg`
    2. ==>
    3. output =Popen(["mycmd","myarg"], stdout=PIPE).communicate()[0]
            例2:间接执行shell管道命令
    1. output=`dmesg | grep hda`
    2. ==>
    3. p1 =Popen(["dmesg"], stdout=PIPE)
    4. p2 =Popen(["grep","hda"], stdin=p1.stdout, stdout=PIPE)
    5. output = p2.communicate()[0]
            例3:间接执行os.system()
    1. sts = os.system("mycmd"+" myarg")
    2. ==>
    3. p =Popen("mycmd"+" myarg", shell=True)
    4. sts = os.waitpid(p.pid,0)[1]
            通过通过返回码判断命令是否运行成功。
    1. try:
    2. retcode = call("mycmd"+" myarg", shell=True)
    3. if retcode <0:
    4. print>>sys.stderr,"Child was terminated by signal",-retcode
    5. else:
    6. print>>sys.stderr,"Child returned", retcode
    7. exceptOSError, e:
    8. print>>sys.stderr,"Execution failed:", e
            





  • 相关阅读:
    Codeforces 177G2 Fibonacci Strings KMP 矩阵
    Codeforces Gym100187C Very Spacious Office 贪心 堆
    Codeforces 980F Cactus to Tree 仙人掌 Tarjan 树形dp 单调队列
    AtCoder SoundHound Inc. Programming Contest 2018 E + Graph (soundhound2018_summer_qual_e)
    BZOJ3622 已经没有什么好害怕的了 动态规划 容斥原理 组合数学
    NOIP2016提高组Day1T2 天天爱跑步 树链剖分 LCA 倍增 差分
    Codeforces 555C Case of Chocolate 其他
    NOIP2017提高组Day2T3 列队 洛谷P3960 线段树
    NOIP2017提高组Day2T2 宝藏 洛谷P3959 状压dp
    NOIP2017提高组Day1T3 逛公园 洛谷P3953 Tarjan 强连通缩点 SPFA 动态规划 最短路 拓扑序
  • 原文地址:https://www.cnblogs.com/fireflow/p/4841432.html
Copyright © 2011-2022 走看看