Python标准库 - subproce

发布时间:2019-07-22 10:14:30编辑:auto阅读(1581)


    编写Python脚本时, 经常要执行Linux操作系统命令, 如mkdir zzzz. 目前比较推荐的方法是使用subprocess模块.



    通过该模块的帮助文档, 可看到其主要提供了4个API, 和相应的使用说明.


    Main API

    ========

    call(...): Runs a command, waits for it to complete, then returns

        the return code.

    check_call(...): Same as call() but raises CalledProcessError()

        if return code is not 0

    check_output(...): Same as check_call() but returns the contents of

        stdout instead of a return code

    Popen(...): A class for flexibly executing a command in a new process



    结合API的说明来看, 若执行简单的命令, 像前面所说mkdir zzzz, 前三个API都可以, 只是处理细节稍有不同.


    In [54]: subprocess.call("mkdir /tmp/zzzz", shell=True)

    Out[54]: 0


    In [55]: subprocess.call("mkdir /tmp/zzzz", shell=True)

    mkdir: cannot create directory `/tmp/zzzz': File exists

    Out[55]: 1



    In [56]: subprocess.check_call("mkdir /tmp/zzzz", shell=True)

    Out[56]: 0


    In [57]: subprocess.check_call("mkdir /tmp/zzzz", shell=True)

    mkdir: cannot create directory `/tmp/zzzz': File exists

    ---------------------------------------------------------------------------

    CalledProcessError                        Traceback (most recent call last)

    <ipython-input-57-2a531671f16e> in <module>()

    ----> 1 subprocess.check_call("mkdir /tmp/zzzz", shell=True)


    /usr/local/python27/lib/python2.7/subprocess.pyc in check_call(*popenargs, **kwargs)

        184         if cmd is None:

        185             cmd = popenargs[0]

    --> 186         raise CalledProcessError(retcode, cmd)

        187     return 0

        188


    CalledProcessError: Command 'mkdir /tmp/zzzz' returned non-zero exit status 1



    In [59]: subprocess.check_output("mkdir /tmp/zzzz", shell=True)

    Out[59]: ''


    In [60]: subprocess.check_output("mkdir /tmp/zzzz", shell=True)

    mkdir: cannot create directory `/tmp/zzzz': File exists

    ---------------------------------------------------------------------------

    CalledProcessError                        Traceback (most recent call last)

    <ipython-input-60-4911eea4ecd3> in <module>()

    ----> 1 subprocess.check_output("mkdir /tmp/zzzz", shell=True)


    /usr/local/python27/lib/python2.7/subprocess.pyc in check_output(*popenargs, **kwargs)

        217         if cmd is None:

        218             cmd = popenargs[0]

    --> 219         raise CalledProcessError(retcode, cmd, output=output)

        220     return output

        221


    CalledProcessError: Command 'mkdir /tmp/zzzz' returned non-zero exit status 1



    又若执行复杂的命令或脚本, 需要获取其标准输出, 和标准错误输出, 就要用到Popen接口了. 前三个API, 其实是第四个的简化版, 是将参数直接传给了Popen的构造函数, 不过大部分参数都是保留了默认值, 来看下该构造函数的样子.


    def __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):


    注意参数shell=False, 其含义为, 是否将args(要执行的命令)置于操作系统的shell环境中运行.



    下面给出一个代码段, 用到了Popen, 算是对subprocess模块的小结.


    #!/usr/bin/env python

    # -*- coding: utf-8 -*-


    import subprocess


    def exec_cmd(cmd):

        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,

                                stderr=subprocess.PIPE, shell=True)


        stdout, stderr = proc.communicate()


        if proc.returncode != 0:

            return proc.returncode, stderr


        return proc.returncode, stdout


    def main():

        cmd = "ls -l"

        # cmd = "ls -lz"


        returncode, stdoutdata = exec_cmd(cmd)

        print str(returncode) + " - " + stdoutdata


    if __name__ == '__main__':

        main()


关键字