Python执行外部命令subprocess
来自CloudWiki
Linux中的使用
subprocess.run()是官方推荐使用的方法,几乎所有的工作都可以由它来完成。首先来看一下函数原型:
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None)
该函数返回一个CompletedProcess类(有属性传入参数及返回值)的实例,虽然该函数的参数有很多,但是我们只需要知道几个常用的就可以了。
- args代表需要在操作系统中执行的命令,可以是字符串形式(要求shell=True),也可以是列表list类型。
- *代表可变参数,一般是列或字典形式。
- stdin、stdout、stderr指定了可执行程序的标准输入、标准输出、标准错误文件句柄。
- shell代表着程序是否需要在shell上执行,当想使用shell的特性时,设置shell=True,这样就可以使用shell指令的管道、文件名称通配符、环境变量等,不过Python也提供了许多类shell的模块,如glob、fnmatch、os.walk()、os.path.expandvars()、os.path.expanduser()和shutil。
- check如果check设置为True,就检查命令的返回值,当返回值为非0时,将抛出CalledProcessError异常。
- timeout设置超时时间,如果超时,则强制kill掉子进程。
执行命令
在Linux系统中如果我们执行一个Linux命令并获取它的返回值,可有如下两种方法,
方法一
>>> import subprocess >>> a=subprocess.run("ls -l /dev/null",shell=True) crw-rw-rw- 1 root root 1, 3 Feb 9 17:23 /dev/null >>> a CompletedProcess(args='ls -l /dev/null', returncode=0) >>> a.args 'ls -l /dev/null' >>> a.returncode 0
方法二
>>> import subprocess >>> b=subprocess.run(["ls","-l","/dev/null"]) crw-rw-rw- 1 root root 1, 3 Feb 9 17:23 /dev/null >>> b CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0) >>> b.args ['ls', '-l', '/dev/null'] >>> b.returncode 0
执行脚本
[root@localhost ~]# chmod 777 /root/test.sh [root@localhost ~]# sudo python3 Python 3.7.5 (default, Apr 16 2020, 22:32:00) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import subprocess >>> s= subprocess.run(['/root/test.sh']) Hello World >>> s CompletedProcess(args=['/root/test.sh'], returncode=0) >>> s.args ['/root/test.sh'] >>> s.returncode 0
捕获脚本输出
>>> a=subprocess.run("ls -l /dev/null",shell=True,stdout=subprocess.PIPE) >>> a CompletedProcess(args='ls -l /dev/null', returncode=0, stdout=b'crw-rw-rw- 1 root root 1, 3 Feb 9 17:23 /dev/null\n') >>> a.stdout b'crw-rw-rw- 1 root root 1, 3 Feb 9 17:23 /dev/null\n'
捕获执行异常
如果传入参数check=True,当returncode不为0时,将会抛出subprocess.CalledProcessError异常;
如果传输timeout参数,当运行时间超过timeout时就会抛出TimeoutExpired异常
>>> a=subprocess.run("exit 1",shell=True,check=True)
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/Python3/lib/python3.6/subprocess.py", line 418, in run output=stdout, stderr=stderr) subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1.
>>> a=subprocess.run("sleep 1",shell=True,timeout=2)
>>> a=subprocess.run("sleep 3",shell=True,timeout=2)
Traceback (most recent call last): File "/usr/local/Python3/lib/python3.6/subprocess.py", line 405, in run stdout, stderr = process.communicate(input, timeout=timeout) File "/usr/local/Python3/lib/python3.6/subprocess.py", line 843, in communicate stdout, stderr = self._communicate(input, endtime, timeout) File "/usr/local/Python3/lib/python3.6/subprocess.py", line 1540, in _communicate self.wait(timeout=self._remaining_time(endtime)) File "/usr/local/Python3/lib/python3.6/subprocess.py", line 1449, in wait raise TimeoutExpired(self.args, timeout) subprocess.TimeoutExpired: Command 'sleep 3' timed out after 1.9999209220113698 seconds During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/Python3/lib/python3.6/subprocess.py", line 410, in run stderr=stderr) subprocess.TimeoutExpired: Command 'sleep 3' timed out after 2 seconds >>>
Windows中的使用
使用subprocess模块可以方便地执行操作系统支持的命令,可与其他应用程序结合使用。因此,Python也常被称为胶水语言。
>>> a=subprocess.run('ipconfig',shell=True,stdout=subprocess.PIPE,encoding="gb2312")
>>> a.stdout
其中encoding指定了windows的编码方式。
>>> a=subprocess.run('dir',shell=True,stdout=subprocess.PIPE,encoding="gb2312")
>>> a.stdout