如何在Python中调用外部命令?
为了在pythonenv中运行外部命令,或者启动守护进程,或者也许调用命令并捕获其输出,Python支持多种调用外部命令的方法。
是否需要保留命令的输出,或将输入发送到命令,或控制其生命周期,取决于方法的要求。
Subprocess
Subprocess是python(3.5+版本)中推荐的模块,用于执行外部命令。使用subprocess模块的call方法,可以在python函数内调用外部命令。
Python 3.6.8 (default, Apr 25 2019, 21:02:35) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import subprocess >>> subprocess.call(['ls', '-l']) total 8 drwxr-xr-x 4 XXXXX sw 4096 Oct 1 17:37 python_samples drwxr-xr-x 5 XXXXX sw 4096 Sep 29 19:53 venv 0 >>>
将输出重定向到文件
为了将输出重定向到文件,请使用with函数打开文件并使用stdout参数。
Python 3.6.8 (default, Apr 25 2019, 21:02:35) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import subprocess >>> with open('output.txt', 'w') as f: ... subprocess.call(['whoami'], stdout=f) ... >>> exit()-bash-4.2$ more output.txt User
将参数作为输入从stdin传递到命令
使用call()。打开文件并使用stdin参数传递句柄。
-bash-4.2$ python3 Python 3.6.8 (default, Apr 25 2019, 21:02:35) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import subprocess >>> with open('output.txt', 'r') as f: ... subprocess.call(['more'], stdin =f) ... user >>>
使用shell=True,可以将shell命令传递给call()函数。
-bash-4.2$ python3 Python 3.6.8 (default, Apr 25 2019, 21:02:35) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import subprocess >>> subprocess.call('ls -la', shell=True) total 20 drwxr-xr-x 4 sradhakr sw 4096 Oct 17 15:42 . drwxr-xr-x 8 sradhakr sw 8192 Oct 8 13:40 .. -rw-r--r-- 1 sradhakr sw 9 Oct 17 15:42 output.txt drwxr-xr-x 4 sradhakr sw 4096 Oct 1 17:37 python_samples drwxr-xr-x 5 sradhakr sw 4096 Sep 29 19:53 venv >>>
如果命令来自不受信任的来源,则使用shell=True会带来安全风险。例如,使用用户输入,如果我们收到诸如rm–rf/之类的命令,则对于文件系统可能是危险的命令。
为了捕获字符串中的命令输出,请使用subprocess.check_output(),
import subprocess try: output = subprocess.check_output(input('enter command >> '), shell=True) print(output)exceptsubprocess.CalledProcessErroras e: print('exception with returncode: {}, command: {}, output = {}'.format(e.returncode, e.cmd, e.output))
输出结果
enter command >> whoami b'user\n'
exit命令代码
exit命令决定命令处理的成败。call()的返回值是退出代码,它决定命令处理的结果。
Python 3.6.8 (default, Apr 25 2019, 21:02:35) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import subprocess >>> print("return code {}".format(subprocess.call('ls -la', shell=True))) total 20 drwxr-xr-x 4 sradhakr sw 4096 Oct 17 15:42 . drwxr-xr-x 8 sradhakr sw 8192 Oct 8 13:40 .. -rw-r--r-- 1 sradhakr sw 9 Oct 17 15:42 output.txt drwxr-xr-x 4 sradhakr sw 4096 Oct 1 17:37 python_samples drwxr-xr-x 5 sradhakr sw 4096 Sep 29 19:53 venv return code 0
为了获得关于外部命令处理的额外信息,还有一个名为subprocess.check_call()的额外方法。
import subprocess try: print(subprocess.check_call(['cat','random.txt'])) exceptsubprocess.CalledProcessErroras e: print('exception: returncode: {}, command: {}'.format(e.returncode, e.cmd))
输出结果
cat: random.txt: No such file or directory exception: returncode: 1, command: ['cat', 'random.txt']