envoy
是对 Python 标准库中 subprocess
模块的封装, 虽然功能对比原生 subprocess
来说少了很多,但是更易于使用,Github 项目地址
代码解析
envoy
只有一个文件,两百多行代码,非常的简单
tree envoy |
envoy
可以非常轻松通过管道传递数据
from envoy.core import run |
我们先看看 run
函数
run
函数接接收 命令,管道数据,超时时间,kill
超时时间,扩展环境变量,执行目录 作为参数
run
函数是对 Command.run
的封装,首先通过 expand_args
函数解析命令,通过 Command.run
执行多个命令,如果有多个命令的话,将上个命令的输出传递给下一个命令,实现管道间的数据传递,并返回一个 Response
对象
def run(command, data=None, timeout=None, kill_timeout=None, env=None, cwd=None): |
我们再看看 envoy
是如何解析我们传入的命令的
如果传入的类型的是 str
或者 unicode
, 则通过 shelx
模块对其进行解析成 subprocess
需要的格式
def expand_args(command): |
我们手动传入一条命令,看一下它的返回
from envoy.core import expand_args |
我们再仔细看一下,envoy
里面是如何通过管道传递数据的
首先 初始化一个 history
列表,保存每一次执行的命令,如果 len(history) > 0
,也说明执行的命令超过一条,则将上条命令的 std_out
前 10 KiB
的数据赋值给 data
再将 data
传递给 Command.run
方法,也就是下个命令的 std_in
def run(command, data=None, timeout=None, kill_timeout=None, env=None, cwd=None): |
envoy
中最关键的就是 Command.run
这个方法了,我们来看看它是如何封装 subprocess
的
Command
的构造函数接收一个命令作为参数
run
方法则比较复杂,里面定义了一个 target
函数,target
函数封装 subprocess.Popen
,然后将管道中的数据传入 communicate
方法
然后启动了一个新的线程,等待线程执行完成或者超时,并做一些检查 以保证进程完全退出,最后返回 std_out
和 std_err
class Command(object): |
总结
envoy
的代码还是很简单的,代码里面也没有用什么黑魔法,毕竟只是一个简单的封装