You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lrpyopsr/source_code_learning

61 lines
3.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Python Fire可以做什么
这是一个通过暴露复杂系统内部接口利用管道和CLI来方便测试的工具。
它可以自动扫描module, object, class, function并自动构建管道
Expose functionality to user by archive them in a function / module / object / class / dict
# Python fire 源码分析:
## __main__.py
主要负责import被使用的module或者file将其导入Fire.fire()函数。
## trace.py
此module具有用于跟踪fire执行状况的类。fire的执行被分割为数个步骤它们取值属于如下集合
(INITIAL_COMPONENT,INSTANTIATED_CLASS,CALLED_ROUTINE,CALLED_CALLABLE,ACCESSED_PROPERTY,COMPLETION_SCRIPT,INTERACTIVE_MODE
)
FireTrace由一系列FireTraceElement对象组成。每个元素
表示一个fire执行时的操作。一项行动可能是实例化类、调用例程或访问属性。
每个操作都使用参数并产生一个新组件。最后一部分
由Fire序列化为stdout并由Fire方法返回。如果
出现Fire用法错误例如提供的参数不足无法调用
一个函数则该Error将在trace中被capture并且final component将被设定为None。
## inspect.py/inspectutils.py
提供调用操作的功能支持
## core.py
### _Fire(component, args, parsed_flag_args, context, name=None)
这是python fire的核心部分完成fire程序的核心逻辑。几种参数含义如下
* component: 是fire构建CLI的初始元素可以是module, class, routine, object...
* args: 待component使用的参数序列
* parsed_flag_args: 启动fire的flag定制化一些fire行为
* context: 调用fire时的local和global变量
* name: 可选的名字在interactive模式使用
fire的一般执行过程如下
1. 检查并处理flag(--xxx)
1. 选择当前component作为当前被处理的对象根据参数的类型
* 是class则实例化被使用的class
* 是routine则调用该routine
* 是sequence使用紧接的参数访问sequence
* 否则,尝试用紧接的属性访问该对象
* 否则如果是callable的示例调用
1. 返回上一个步骤重复直到所有args被消耗
当不再能够继续执行时fire将结果序列化后输出。
我们可以注意到其比较核心的功能需要用到代码分析技术而fire的实现如下
```
is_callable = inspect.isclass(component) or inspect.isroutine(component)
is_callable_object = callable(component) and not is_callable
is_sequence = isinstance(component, (list, tuple))
is_map = isinstance(component, dict) or inspectutils.IsNamedTuple(component)
```
其中主要使用到inspect库的各种isXXX函数。去到这个库的源文件查看可以发现如下十分方便的函数ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction() isgenerator(), istraceback(), isframe(), iscode(), isbuiltin(), isroutine()。
再检视inspect.py文件可以发现大部分的isXXX()的实现用到了python builtins的库函数isinstance()issubclass()getattr()hasattr()...
有了python提供的这些函数就可以实现变量的动态查找和识别然后根据这些变量的不同类别进行不同的操作。
当检测到component是class, routine, callable object时调用_CallAndUpdateTrace()来