【问题标题】:__getattr__ for module running twice on import? [duplicate]__getattr__ 模块在导入时运行两次? [复制]
【发布时间】:2021-03-30 10:08:37
【问题描述】:

当使用__getattr__ 从模块导入对象时,我正在尝试运行一些逻辑,如下所述:__getattr__ on a module

...但逻辑运行两次。为什么会发生这种情况,我该如何阻止它?

main.py

from test import x, y

test.py

def __getattr__(name: str):
    print(f"Imported {name}")

【问题讨论】:

  • 请将您的代码和输出作为文本发布,而不是屏幕截图。
  • 您是否尝试在通话期间检查回溯?
  • @o11c 没有回溯,因为代码执行成功。当我在本地复制它时,以详细模式运行 python 不会显示任何信息。检查 cProfile 显示 5 次调用 test.__getattr__: 5 0.000 0.000 0.000 0.000 test.py:1(__getattr__)
  • @C.Nivs 骗子展示了如何检查回溯。

标签: python python-3.x python-module getattr


【解决方案1】:

您的__getattr__ 为所有属性(包括__path__)返回None,如果模块具有__path__ 属性,则将其视为一个包。

对于一个包,from test import x, y 需要处理名为test.xtest.y 的可能子模块。做这个处理的code首先使用hasattr,来测试test是否已经有xy属性:

elif not hasattr(module, x):
    ...

hasattr 负责第一个__getattr__('x')__getattr__('y') 调用。

第二个__getattr__('x')__getattr__('y') 调用正是您期望发生的调用,以检索test.xtest.y 以进行导入。


您的__getattr__ 不应该为__path__ 等特殊属性返回值。

此外,不相关的,将模块命名为 test 是一个坏主意,因为标准库已经为 Python's own test suite 声明了该名称。

【讨论】:

  • "你的 getattr 对所有属性都返回 None,包括 path" 有什么办法可以防止这种情况发生吗?我仍然想让我的逻辑只运行一次,但我不确定如何让hasattr 在此处为__path__ 返回False
  • 没关系,在name=='__path__'的情况下只需要添加raise AttributeError
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-27
  • 2018-01-07
  • 1970-01-01
相关资源
最近更新 更多