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')
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'
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')
封装一个可以执行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)