关于Abseil库flags在Python导入关联模块间的互访规则问询
Absl Flags 跨模块访问规则说明
核心结论可以直接明确:
你观察到的跨模块访问flags的现象,和模块之间的导入方向、是否存在导入关联完全无关。
absl.flags的实现本质就是所有模块共享同一个进程全局单例的flag注册表,任何模块只要导入absl.flags拿到的FLAGS都是这个全局实例,所有通过DEFINE_*方法注册的flag都会写入这个实例,任意模块都可以直接读取所有已经完成注册的flag。
针对你提供的三个测试文件,运行逻辑完全符合这个规则:
- 程序以
sample.py为入口启动,首先执行导入逻辑:- 导入
sample2模块,触发sample2先执行导入sample3的逻辑 sample3运行时调用DEFINE_string将Flag2注册到全局FLAGS实例sample2运行时调用DEFINE_string将Flag1注册到全局FLAGS实例- 回到
sample.py主逻辑,调用DEFINE_string将name注册到全局FLAGS实例
- 导入
- 后续不管是
sample.py中读取Flag2、还是sample2/sample3中读取name,都是访问同一个全局实例的属性,因此都能正常拿到值。
需要澄清你之前的几个认知偏差:
- 不存在「只有导入定义flag的模块才能访问对应flag」的限制:只要flag已经完成注册到全局注册表,哪怕你完全没导入定义该flag的模块,也可以正常读取
- 不存在「模块需要有导入关联才具备访问权限」的规则:哪怕两个模块完全没有导入关系,只要在同一个进程内运行、都使用
absl.flags,就能互相访问对方注册的flag - 你观察到的「传递性」本质是全局单例的特性,和导入链路的传递性没有关联
另外有一个常见的使用坑需要注意:读取flag的时机必须晚于该flag的注册时机。比如你如果把sample.py中import sample2的语句放到DEFINE_string('name', 'Jane Random', 'Your name.')之后,那么sample2运行时name还没有被注册,读取FLAGS.name就会直接抛出flag未定义的异常。
内容的提问来源于stack exchange,提问作者Anshul Pattoo
相关产品推荐
相关产品推荐

