1

The Problem:

Supposing I have a directory structure like:

root/
    __init__.py
    foo.py
    dir1/
        __init__.py
        bar.py
        dir2/
            __init__.py
            baz.py

where the various python files contain some function called hello_world.

What I want to be able to do is write something like:

import root
root.dir1.foo.hello_world()
root.dir1.dir2.baz.hello_world()

Of course, when I do this, I get a AttributeError: module has no attribute error. This, I think, is due to the "the __init__.py trap" in the docs. How do I manipulate the init files such that I can make the above code run?

Caveats

  • I'd like to avoid deleting the init files because they contain the __all__ parameter, and thats important for my program.
  • I'd also like to avoid writing more than one import statement in the main program, so the solution specified here wont work.
  • I'm using Python 3.6

What I've Tried:

I've tried to get around this by changing the __init__.py files into namespace packages). Unfortunately, this doesn't seem to work. E.g. adding:

__path__ = __import__('pkgutil').extend_path(__path__, __name__)

to the various init files doesn't change anything. Similarly, setting the __path__ attribute directly doesn't solve the problem. E.g. in each init file setting __path__ = ['<string name of child dir>'] doesn't resolve the error.

This is a bit mysterious to me, since the __path__ is supposed to tell python where to look for submodules, and the init files are supposed to be run sequentially, so why cant it figure out where things are?

Notes:

This issue seems to be described in the docs here

1 Answer 1

1

One solution was to put a from . import * after defining the __all__ property in each init file. E.g. in the init in dir1 put:

__all__ = ['foo', 'dir2']
from . import *

This solves the use case, but it seems like the wrong way. Open for better answers.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.