Search code examples
pythonpython-3.xpython-modulegetattr

__getattr__ for module running twice on import?


I'm trying to run some logic when objects are imported from a module by using __getattr__ as described here: __getattr__ on a module

...but the logic runs twice. Why is that happening and how can I stop it?

enter image description here

main.py

from test import x, y

test.py

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

Solution

  • Your __getattr__ returns None for all attributes, including __path__, and if a module has a __path__ attribute, it's treated as a package.

    For a package, from test import x, y needs to handle possible submodules named test.x and test.y. The code that does this handling uses hasattr first, to test whether test already has x and y attributes:

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

    and that hasattr is responsible for the first __getattr__('x') and __getattr__('y') calls.

    The second __getattr__('x') and __getattr__('y') calls are just the ones you'd expect to happen, to retrieve test.x and test.y for the import.


    Your __getattr__ shouldn't return a value for special attributes like __path__.

    Also, unrelated, naming a module test is a bad idea, because the standard library already claimed that name for Python's own test suite.