Chinaunix首页 | 论坛 | 博客
  • 博客访问: 148944
  • 博文数量: 51
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 255
  • 用 户 组: 普通用户
  • 注册时间: 2020-12-30 16:49
文章分类
文章存档

2021年(48)

2020年(3)

我的朋友

分类: Python/Ruby

2021-01-04 14:25:14

在 Python 中调用外部进程是很常见的需求,以下为几种常见的方法。
os.system
这个方法实际上调用的是系统的 C 函数 system(), 命令以字符串的形式传入,在系统子 shell 中执行,和在真实的 shell 执行一致。
优点:可以利用 shell 的管道和重定向等特性来实现比较复杂的命令。
import os


# 使用管道获取所有java进程并强制杀掉
os.system('ps -ef|grep java|cut -c 9-15|xargs kill -9')


# 获取当前目录下所有png图片文件名并重定向到png_list.txt中
os.system('ls *.png > png_list.txt')
复制代码
缺点:外部进程的输出无法被 python 代码捕获,system 函数只返回一个 exit status,此外作为命令传入的字符串必须是有效的命令,否则会出现意想不到的结果。
os.popen
与上一种不同的是,os.popen 会开辟一个管道并将输出通过一个 file-like 的对象返回给调用者,类似 python 中文件操作方法 open 一样。
import os


with os.popen('ls *.png', mode='r') as res:
    result = res.read()
复制代码
subprocess.Popen
这个是 python 自带库 subprocess 中的 Popen 类,作为 os.popen 的替代,拥有更多可选参数。
import subprocess


# 当 shell=True 时,POSIX 类系统默认会调用 /bin/sh 来执行传入的命令
result = subprocess.Popen(['ls', '-l'], shell=True, stdout=subprocess.PIPE).stdout.read()
复制代码
subprocess.call
这个函数拥有类似 Popen 类的可选参数,但是会等待子进程运行完毕再返回一个返回码。
import subprocess


return_code = subprocess.call(['ls', '-l'], shell=True)
复制代码
subprocess.run
这个函数在 python3.5 及以后的版本可用,有几个非常有用的参数可选,该函数返回的是一个 CompletedProcess 对象,通过该对象可以获取标准输入和输出。
import subprocess


# 在shell中执行并获取标准输出和错误
result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# 可以配合 shlex 库分割指令字符串
# subprocess.run(shlex.split('ls -l))
print(result.stdout)
print(result.stderr)


# 对返回值进行检查, 如果子程序返回错误那么抛出一个CalledProcessError的异常
result = subprocess.run(['ls', '-l'],check=True)


# 给子程序加上超时限制, 如果超时, 向上抛出TimeoutExpired异常, 在项目中控制外部进程用时是比较好的习惯
result = subprocess.run(['sleep', '5'], timeout=3)
复制代码
fabric.operations
from fabric import operations


res = operations.local('ls -l', capture=True)


# 在远程服务器上执行命令,但需要提前配置好登陆信息
res = operations.run('cmd')
复制代码
第三方模块 sh
其通过动态解析 $PATH 来执行二进制命令,执行并不是 Python 类或函数,而是用 python 包装了系统 PATH 中的可执行命令,也就是说系统路径中所有命令都是可以执行的。
# 安装
pip install sh


# 执行各种系统命令
sh.ls('-l', '/data')
sh.ifconfig()


# 使用管道,并获取返回值
count = sh.wc(sh.ls('-l'), '-l')


# 甚至可以使用子命令
sh.git.status()


# 将命令放在后台运行
p = sh.find('-name', 'sh.py', _bg=True)
# 干其他事
p.wait()
复制代码
总结
个人优先推荐官方库中的 subprocess 模块中的 run 函数,简单易用。


作者:kivenckl
链接:
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
阅读(16929) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~