subprocess模块源码介绍

  • 介绍

    subprocess生成新的进程,连接input/output管道,并获取返回码.

  • 常用函数
    subprocess.run() 执行指定命令完成并返回一个包含执行结果的CompletedProcess类的实例。.
    call() 执行指定的命令,返回命令执行状态
    check_call() 执行指定的命令,如果执行成功则返回状态码,否则抛出异常
    check_output() 执行指定的命令,如果执行状态码为0则返回命令执行结果,否则抛出异常
    getoutput(cmd) 接收字符串格式的命令,执行命令并返回执行结果
    getstatusoutput(cmd) 执行cmd命令,返回一个元组(命令执行状态,命令执行结果输出)
  • 参数说明

    • args: 执行的shell命令(字符串序列),shell参数值应该为True.
    • shell: shell为True,指定命令通过shell执行.
    • check: 为True,且执行命令的进程以非0状态码退出,则会抛出一个CalledProcessError的异常.
    • stdout,stderr:
    • run() 函数不捕获命令执行结果的正常和错误输出.向获取这些内容传递subprocess.PIPE,然后可以通过返回的CompletedProcess类实例的stdout和stderr属性或捕获相应的内容;
    • call()和check_call()函数返回的是命令执行状态码.
    • check_output() 返回执行命令结果.在结果中捕获错误信息,可以执行stderr=subprocess.STDOUT。
    • input: 该参数值是字节序列.
    • universal_newlines: 影响的是输入与输出的数据格式.
  • subprocess.CompletedProcess类介绍

    表示的是一个已结束进程的状态信息.包含属性如下:

    • args: 加载该进程的参数.
    • returncode 子进程的退出状态码.
    • stdout: 从子进程捕获的stdout.一个字节序列. 指定universal_newlines=True,则该属性值是一个字符串.
    • stderr: 从子进程捕获的stderr。值是一个字节序列或一个字符串。
    • check_returncode(): 如果returncode是一个非0值,则该方法会抛出一个CalledProcessError异常。.
  • 示例

    • run()
      
      In [2]: subprocess.run(["ls","-l"])
      -rw-r--r-- 1 liyuanjie liyuanjie 1350 12月 15 18:33 wireshark.md
      Out[2]: CompletedProcess(args=['ls', '-l'], returncode=0)

    In [3]: subprocess.run(["ls","-l","/dev/null"],stdout=subprocess.PIPE)
    Out[3]: CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0, stdout=b'
    crw-rw-rw- 1 root root 1, 3 12\xe6\x9c\x88 15 07:51 /dev/null\n')

    
    - call()
    

    In [4]: subprocess.call(['ls','-l'])
    In [5]: subprocess.call('ls -l',shell=True)

    In [6]: subprocess.call(['ls','-l'],stdout=subprocess.DEVNULL)
    Out[6]: 0

    In [7]: subprocess.call(['ls','-l','/services'])

    
    - check_call()
    

    In [9]: subprocess.check_call(['ls','-l'])
    In [10]: subprocess.check_call('ls -l',shell=True)

    In [11]: subprocess.check_call('ls -l /services',shell=True)

    
    - check_output()
    

    In [12]: ret = subprocess.check_output(['ls','-l'])
    In [13]: print(ret) 返回的是字节序列.

    In [14]: ret = subprocess.check_output(['ls','-l'],universal_newlines=True)
    In [15]: print(ret) 返回的是字符串.

    
    - getoutput()与getstatusoutput()
    

    In [16]: ret = subprocess.getoutput('ls -l')
    In [17]: print(ret)

    正确情况下:
    In [18]: retcode,output = subprocess.getstatusoutput('ls -l')
    In [19]: print(retcode)
    0
    In [20]: print(output)

    错误情况下:
    In [21]: retcode,output = subprocess.getstatusoutput('ls -l /test')
    In [22]: print(retcode)
    2

    In [23]: print(output)
    ls: cannot access '/test': No such file or directory

subprocess.Popen介绍

该类用于在一个新的进程中执行一个子程序.由于subprocess模块底层的进程创建和管理是由Popen类来处理的. 可以通过subprocess.Popen类提供的灵活的api来完成.

  • Popen的构造函数

    参数说明

    • args: shell命令.
    • bufsize: 指定缓存策略,0表示不缓冲,1表示行缓冲.负数 表示使用系统默认缓冲策略。
    • stdin,stdout,stderr: 分别表示程序标准输入,输出,错误句柄。
    • preexec_fn: 用于指定一个将在子进程运行之前被调用的可执行对象.
    • close_fds: 值为True时,所有文件描述符都将在子进程执行前关闭.
    • shell: 标识是否使用shell作为要执行的程序.
    • cwd: 该函数会在执行这个子进程之前改变当前工作目录.
    • env: 用于指定子进程的环境变量.
    • universal_newlines为True时,则该文件对象的stdin,stdout和stderr将会作为文本流被打开,否则他们将会被作为二进制流被打开。
  • Popen类的实例可调用的方法

    Popen.poll() 检查命令是否已经执行结束.
    wait(timeout=None) 等待子进程结束,返回状态码.
    communicate() 与进程进行交互.
    send_signal(signal) 发送指定的信号给这个子进程
    terminate() 停止该子进程.
    kill() 杀死该子进程.
  • 示例

    In [25]: p = subprocess.Popen('df -hT',stdout=subprocess.PIPE,shell=True)
    In [26]: print(p.stdout.read())
    
    In [2]: p1 = subprocess.Popen(['df','-Th'],stdout=subprocess.PIPE)
    In [3]: p2 = subprocess.Popen(['grep','dev'],stdin=p1.stdout,stdout=subprocess.PIPE)
    
    In [4]: out,err = p2.communicate()
    In [5]: print(out)