subprocess

如果想在系统上执行命令, 应该用subprocess模块

subprocess模块允许你产生新的子进程,连接到input/output/error管道,并且获得它们的返回码(值).  这个模块用来替换下面旧的模块和函数

  • os.system(),
  • os.spawn*(),
  • os.popen*()
  • popen2.*()
  • commands.*()

使用subprocess模块,主要会用到它的Popen类

1、命令以序列的方式执行.

>>> proc = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> stdout, stderr = proc.communicate()         # 获取标准输入和标准输出

2、命令以字符串的方式执行

>>> proc = subprocess.Popen('ls -l', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
>>> stdout, stderr = proc.communicate()        # 获取标准输出和标准错误
  • 命令可以用字符串序列,如果是序列,shell参数应该为Flase (默认), 如果是字符串,shell参数为True,如果shell=True它会在linux shell里面执行,官方文档推荐命令以序列的方式执行,因为用字符串可能会有歧义。
  • communicate 方法可以从process中获取到标准输出和错误

练习:

def sh(cmdline):
    """
    : 执行shell命令返回结果, 等同于subprocess.getoutput(cmdline)
    : params: cmdline 命令
    : return : str
    """
    process = subprocess.Popen(cmdline, stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE, shell=True)
    process.wait()
    stdout, stderr = process.communicate()

    if stdout:
        return str(stdout.strip(), encoding='utf-8')
    if stderr:
        return str(stderr.strip(), encoding='utf-8')
sh

Python3中还支持几个方法:

  • getoutput    获取命令的执行结果,返回str
  • getstatusoutput 获取命令执行的返回值、结果,返回tuple

getoutput

>>> subprocess.getoutput('ls -l')
'total 261868\n-rw-------. 1 root root      2769 Mar 27  2016 anaconda-ks.cfg\n-rw-r--r--  1 root root       295 May 14 12:28 bash.py\n-rw-------  1 root root      3485 Apr 14 15:54 dead.letter\n-rwxr-xr-x  1 root root       591 Apr 27 10:07 get_estab.py\ndrwxr-xr-x  5 root root      4096 Jan 13 15:38 gitdir\n-rw-r--r--  1 root root    174895 Nov  2  2016 google.log\n-rwxr-xr-x  1 root root      3351 Apr 28 09:02 homework.py\n-rw-r--r--  1 root root       255 Nov 28 21:52 init_hostname.sh\n-rw-r--r--. 1 root root     20341 Mar 27  2016 install.log\n-rw-r--r--  1 root root       306 May 13 22:47 iw.py\ndrwxr-xr-x  3 root root      4096 Apr 24 16:31 learpython\n-rwxr-xr-x  1 root root       725 Apr 18 17:21 monitor_zh.sh\ndrwxr-xr-x  2 root root      4096 Apr 22 00:30 openapi\n-rw-r--r--  1 root root 189688255 Dec 12 19:40 openapi.out\n-rw-r--r--  1 root root  78200937 Nov  2  2016 pic_access.log\ndrwxr-xr-x  3 root root      4096 Mar 30 21:09 ps_mem\n-rw-r--r--  1 root root      1765 Apr 28 17:13 userdb.pkl'
subprocess.getoutput

getstatusoutput

>>> subprocess.getstatusoutput('ls -l')
(0, 'total 261868\n-rw-------. 1 root root      2769 Mar 27  2016 anaconda-ks.cfg\n-rw-r--r--  1 root root       295 May 14 12:28 bash.py\n-rw-------  1 root root      3485 Apr 14 15:54 dead.letter\n-rwxr-xr-x  1 root root       591 Apr 27 10:07 get_estab.py\ndrwxr-xr-x  5 root root      4096 Jan 13 15:38 gitdir\n-rw-r--r--  1 root root    174895 Nov  2  2016 google.log\n-rwxr-xr-x  1 root root      3351 Apr 28 09:02 homework.py\n-rw-r--r--  1 root root       255 Nov 28 21:52 init_hostname.sh\n-rw-r--r--. 1 root root     20341 Mar 27  2016 install.log\n-rw-r--r--  1 root root       306 May 13 22:47 iw.py\ndrwxr-xr-x  3 root root      4096 Apr 24 16:31 learpython\n-rwxr-xr-x  1 root root       725 Apr 18 17:21 monitor_zh.sh\ndrwxr-xr-x  2 root root      4096 Apr 22 00:30 openapi\n-rw-r--r--  1 root root 189688255 Dec 12 19:40 openapi.out\n-rw-r--r--  1 root root  78200937 Nov  2  2016 pic_access.log\ndrwxr-xr-x  3 root root      4096 Mar 30 21:09 ps_mem\n-rw-r--r--  1 root root      1765 Apr 28 17:13 userdb.pkl')
getstatusoutput

封装一个可以执行linux命令的函数

import subprocess
from collections import namedtuple

exec_command = namedtuple('exec_command', ('cmd', 'out', 'exitcode'))


# py3
def bash(cmd: str, *, cwd: str = None, **kwargs) -> namedtuple:
    """
    执行bash命令, 返回一个包含输出以及退出码的命名元组
    """
    try:
        out = subprocess.run(cmd, cwd=cwd, shell=True, text=True, check=True,
                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                             executable='/bin/bash', **kwargs).stdout
        exitcode = 0
    except subprocess.CalledProcessError as exc:
        out = exc.output
        exitcode = exc.returncode
    if out[-1:] == '\n':
        out = out[:-1]
    return exec_command(cmd, out, exitcode)

 

 

 

 

 

  

 

posted @ 2017-05-14 16:42  opss  阅读(390)  评论(0编辑  收藏  举报