• subprocess


    http://docs.python.org/library/subprocess.html

    1.执行shell命令

    官方定义:

    subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)

    Run the command described by args. Wait for command to complete, then return the returncode attribute.

    #!/usr/bin/env python  
       #Python wrapper for the ls command  
        import subprocess  
        subprocess.call(["ls","-l"]) 
        或者subprocess.call("ls -l",shell=True)

    2.subprocess.Popen

       class 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需要是一个字符串,或者包含程序参数的列表。要执行的程序一般就是这个列表的第一项,或者是字符串本身。但是也可以用executable参数来明确指出。当executable参数不为空时,args里的第一项仍被认为是程序的“命令名”,不同于真正的可执行文件的文件名,这个“命令名”是一个用来显示的名称,例如执行*nix下的 ps 命令,显示出来的就是这个“命令名”。

    在*nix下,当shell=False(默认)时,Popen使用os.execvp()来执行子程序。args一般要是一个列表。如果args是个字符串的话,会被当做是可执行文件的路径,这样就不能传入任何参数了。

    例子(借用别人的):

    p = subprocess.Popen("app2.exe", stdin = subprocess.PIPE, /  
        stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = False)  
    p.stdin.write('3/n')  
    p.stdin.write('4/n')  
    print p.stdout.read()  
      
    #---- 结果 ----   
    input x:   
    input y:   
    3 + 4 = 7  

    app2 code:

    #include <iostream>   
    using namespace std;  
    int main(int argc, const char *artv[])  
    {  
        int x, y;  
        cout << "input x: " << endl;  
        cin >> x;  
        cout << "input y: " << endl;  
        cin >> y;  
        cout << x << " + " << y << " = " << x + y << endl;  
        return 0;  
    }  

    Popen对象有以下方法:

    Popen.poll()
    检查子进程是否已结束,设置并返回 returncode 属性。

    Popen.wait()
    等待子进程结束,设置并返回 returncode 属性。

    注意:如果子进程输出了大量数据到stdout或者stderr的管道,并达到了系统 pipe的缓存大小的话,子进程会等待父进程读取管道,而父进程此时正wait着的话,将会产生传说中的死锁,后果是非常严重滴。建议使用communicate()来避免这种情况的发生。

    Popen.communicate(input=None)
    和子进程交互:发送数据到stdin,并从stdout和stderr读数据,直到收到EOF。等待子进程结束。可选的input如有有的话,要为字符串类型。
    此函数返回一个元组: (stdoutdata, stderrdata) 。
    注意,要给子进程的stdin发送数据,则Popen的时候,stdin要为PIPE;同理,要可以收数据的话,stdout或者stderr也要为 PIPE。

    注意:读到的数据会被缓存在内存里,所以数据量非常大的时候要小心了。

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

    注意:windows下目前只支持发送SIGTERM,等效于下面的terminate()

    Popen.terminate()
    停止子进程。Posix下是发送SIGTERM信号。windows下是调用TerminateProcess()这个API。

    Popen.kill()
    杀死子进程。Posix下是发送SIGKILL信号。windows下和terminate()无异。

    Popen.stdin
    如果stdin参数是PIPE,此属性就是一个文件对象,否则为None

    Popen.stdout
    如果stdout参数是PIPE,此属性就是一个文件对象,否则为None

    Popen.stderr
    如果stderr参数是PIPE,此属性就是一个文件对象,否则为None

    Popen.pid
    子进程的进程号。注意,如果shell参数为True,这属性指的是子shell的进程号。

    Popen.returncode
    子程序的返回值,由poll()或者wait()设置,间接地也由communicate()设置。
    如果为None,表示子进程还没终止。
    如果为负数-N的话,表示子进程被N号信号终止。(仅限*nux)

    用subprocess来代替其他函数

    在这节里,举一些常用的例子,都可以用subprocess来完成,我们假定是用 “from subprocess import *” 来导入模块的:

    代替shell命令:

    output=`mycmd myarg`
    等效于
    output = Popen(["mycmd", "myarg"], stdout=PIPE).communicate()[0]

    代替shell管道:

    output=`dmesg | grep hda`
    等效于
    p1 = Popen(["dmesg"], stdout=PIPE)
    p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
    output = p2.communicate()[0]

    代替os.system()

    sts = os.system(“mycmd” + ” myarg”)
    等效于
    p = Popen(“mycmd” + ” myarg”, shell=True)
    sts = os.waitpid(p.pid, 0)[1]

    注意:

    • 通常并不需要用shell来调用程序。
    • 用subprocess可以更方便地得到子程序的返回值。

    其实,更真实的替换是:

    try:
    retcode = call(“mycmd” + ” myarg”, shell=True)
    if retcode < 0:
    print >>sys.stderr, “Child was terminated by signal”, -retcode
    else:
    print >>sys.stderr, “Child returned”, retcode
    except OSError, e:
    print >>sys.stderr, “Execution failed:”, e

    代替os.spawn系列
    P_NOWAIT的例子

    pid = os.spawnlp(os.P_NOWAIT, “/bin/mycmd”, “mycmd”, “myarg”)
    等效于
    pid = Popen(["/bin/mycmd", "myarg"]).pid

    P_WAIT的例子

    retcode = os.spawnlp(os.P_WAIT, “/bin/mycmd”, “mycmd”, “myarg”)
    等效于
    retcode = call(["/bin/mycmd", "myarg"])

    Vector的例子

    os.spawnvp(os.P_NOWAIT, path, args)
    等效于
    Popen([path] + args[1:])

    关于环境变量的例子

    os.spawnlpe(os.P_NOWAIT, “/bin/mycmd”, “mycmd”, “myarg”, env)
    等效于
    Popen(["/bin/mycmd", "myarg"], env={“PATH”: “/usr/bin”})

    代替os.popen(), os.popen2(), os.popen3()

    pipe = os.popen(“cmd”, ‘r’, bufsize)
    等效于
    pipe = Popen(“cmd”, shell=True, bufsize=bufsize, stdout=PIPE).stdout

    pipe = os.popen(“cmd”, ‘w’, bufsize)
    等效于
    pipe = Popen(“cmd”, shell=True, bufsize=bufsize, stdin=PIPE).stdin

    (child_stdin, child_stdout) = os.popen2(“cmd”, mode, bufsize)
    等效于
    p = Popen(“cmd”, shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, close_fds=True)
    (child_stdin, child_stdout) = (p.stdin, p.stdout)

    (child_stdin, child_stdout, child_stderr) = os.popen3(“cmd”, mode, bufsize)
    等效于
    p = Popen(“cmd”, shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
    (child_stdin, child_stdout, child_stderr) = (p.stdin, p.stdout, p.stderr)

    (child_stdin, child_stdout_and_stderr) = os.popen4(“cmd”, mode, bufsize)
    等效于
    p = Popen(“cmd”, shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
    (child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout)

    *nix下,os.popen2, os.popen3, os.popen4 也可以接受一个列表做为执行的命令,这时参数会被直接传给程序,而不经过shell的解释转换。如下:

    (child_stdin, child_stdout) = os.popen2(["/bin/ls", "-l"], mode, bufsize)
    等效于
    p = Popen(["/bin/ls", "-l"], bufsize=bufsize, stdin=PIPE, stdout=PIPE)
    (child_stdin, child_stdout) = (p.stdin, p.stdout)

    返回值处理:

    pipe = os.popen(“cmd”, ‘w’)

    rc = pipe.close()
    if rc != None and rc % 256:
    print “There were some errors”
    等效于
    process = Popen(“cmd”, ‘w’, shell=True, stdin=PIPE)

    process.stdin.close()
    if process.wait() != 0:
    print “There were some errors”

    代替popen2模块里的函数:

    (child_stdout, child_stdin) = popen2.popen2(“somestring”, bufsize, mode)
    等效于
    p = Popen(["somestring"], shell=True, bufsize=bufsize, stdin=PIPE, stdout=PIPE, close_fds=True)
    (child_stdout, child_stdin) = (p.stdout, p.stdin)

    *nix下,popen2 也可以接受一个列表做为执行的命令,这时参数会被直接传给程序,而不经过shell的解释转换。如下:

    (child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, mode)
    等效于
    p = Popen(["mycmd", "myarg"], bufsize=bufsize, stdin=PIPE, stdout=PIPE, close_fds=True)
    (child_stdout, child_stdin) = (p.stdout, p.stdin)

    popen2.Popen3 and popen2.Popen4 基本上也能用 subprocess.Popen 代替,除了以下几点要注意:

    • 执行失败的时候Popen会抛出异常
    • capturestderr参数用stderr代替
    • stdin=PIPEstdout=PIPE 必须要指定
    • popen2默认会关掉所有文件描述符,而Popen要指定close_fds=True

    3.shlex.split()可以被用于序列化复杂的命令参数

    >>> command = raw_input()
    cd d: dir
    >>> command
    'cd d: dir'
    >>> import shlex
    >>> args = shlex.split(command)
    >>> args
    ['cd', 'd:', 'dir']

    import subprocess
    
    p = subprocess.Popen(cmd, stderr = subprocess.STDOUT, stdout= subprocess.PIPE, shell = True)
    return_str=p.stdout.read()
    #stderr output handle way as the stdout
    
  • 相关阅读:
    jQuery加载
    2.第一个flask web程序
    [转]前端懒加载以及预加载
    [转]当你在浏览器中输入 google.com 并且按下回车之后发生了什么?
    [转]如何让在FLASH不浮动在层之上
    逻辑回归基础梳理
    线性回归基础梳理
    [傻瓜式一步到位] 阿里云服务器Centos上部署一个Flask项目
    Java学习之"Hello World"
    JDK安装及Java环境变量配置
  • 原文地址:https://www.cnblogs.com/lovemo1314/p/2682000.html
Copyright © 2020-2023  润新知