diff --git a/source_code_learning b/source_code_learning index a9920b9..0f14314 100644 --- a/source_code_learning +++ b/source_code_learning @@ -3,23 +3,52 @@ 它可以自动扫描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执行状况的类。 +FireTrace由一系列FireTraceElement对象组成。每个元素 +表示一个fire执行时的操作。一项行动可能是实例化类、调用例程或访问属性。 +每个操作都使用参数并产生一个新组件。最后一部分 +由Fire序列化为stdout,并由Fire方法返回。如果 +出现Fire用法错误,例如提供的参数不足,无法调用 +一个函数,则该Error将在trace中被capture并且final component将被设定为None。 + ## core.py -原型:Fire(component=None, command=None, name=None). + +### _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. 从参数列表pop一个参数 -1. 根据参数的类型 -1. 实例化被使用的class -2. 或者调用命令所指向的function -3. 或者查找命令指向的属性 -1. 返回步骤1 -当不再能够继续执行时,fire将结果序列化后输出 - -我们可以注意到其比较核心的功能需要用到静态代码分析、反射、模式匹配 \ No newline at end of file +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() \ No newline at end of file