Python导入本地monotonic子模块覆盖pymongo内置模块问题咨询
问题解答
1. 本地monotonic/monotonic.py匹配pymongo.monotonic导入路径的原因
你使用的pymongo 3.12.1版本中,自带的pymongo.monotonic模块存在兼容逻辑:优先尝试从全局环境导入第三方monotonic库的monotonic方法作为time使用,导入失败才会 fallback 到标准库time模块的对应实现。
Python 3.3+ 支持隐式命名空间包,无需__init__.py即可将目录识别为Python包。你运行main.py时sys.path首位是eden/目录,Python导入模块时会按sys.path顺序优先查找该目录,你本地的monotonic/目录会被识别为名为monotonic的包,优先于site-packages里的第三方依赖被命中,所以会匹配到pymongo的导入逻辑。
2. 本地monotonic.py无time对象却未直接报错的原因
pymongo内部的导入语句是from monotonic import monotonic as time,并不是导入time对象。你本地的monotonic命名空间包下存在同名的monotonic.py模块,刚好匹配from monotonic import monotonic的导入规则,会直接将monotonic.monotonic模块作为导入结果返回,全程不会触发ImportError。
3. 整个模块被赋值给_time的原因
你本地的monotonic/monotonic.py是被作为模块导入的,刚好匹配pymongofrom monotonic import monotonic as time的导入规则,所以这个模块对象会被赋值给pymongo.monotonic.time,最终被from pymongo.monotonic import time as _time导出为_time,调用_time()时就会触发module object is not callable报错。
4. 仅<x>/<x>.py结构触发异常的原因
只有当包名和包下的模块名完全相同时,才会刚好命中from x import x的导入规则:
- 如果目录和文件名不同(比如
tonic/monotonic.py、monotonic/tonic.py),from monotonic import monotonic语句会直接抛出ImportError,触发pymongo的 fallback 逻辑,使用标准库的time实现,不会报错 - 如果直接把
monotonic.py放在eden/根目录,导入时会识别为monotonic模块,from monotonic import monotonic会尝试从该模块导入monotonic属性,找不到就会抛ImportError走 fallback,同样不会触发异常。
内容的提问来源于stack exchange,提问作者flaschbier

