0

Given a directory with the following structure:

├── foo
│   ├── bar
│   │   └── baz.py
│   └── bar.py
└── foo.py

and the following file contents:

foo.py

class Foo:
    pass

foo/bar.py

class Bar:
    pass

foo/bar/baz.py

class Baz:
    pass

I would love to be able to do all of these things from some other file:

from foo import Foo
from foo.bar import Bar
from foo.bar.baz import Baz

i.e. as if the definitions in each file were "merged" with the module definitions comprising the directory with the same name. How can I accomplish this in a dynamic way (whether involving __init__.py or otherwise) that won't require me to manually specify each path?

When I place empty __init__.py files in each directory and attempt to perform the above imports, I receive the following error:

Traceback (most recent call last):
  File "test.py", line 1, in <module>
    from foo import Foo
ImportError: cannot import name 'Foo'

which seems to me to suggest that the foo.py file has been overridden by the foo directory so that the definitions in foo.py are not visible.

3
  • do you mean you wish you could avoid typing out the foo.bar.baz? in which case yes this is fairly easy with an __init__.py file. Commented Apr 3, 2016 at 0:00
  • No, I'm fine with typing the imports exactly as shown. I've updated the question with the error I get when I attempt to do so. Commented Apr 3, 2016 at 0:04
  • When I say "in a dynamic way that won't require me to manually specify each path", what I mean is that I wouldn't like to have to update the __init__.py files, for example, to include each new file/directory for which I want this behavior. Commented Apr 3, 2016 at 0:10

1 Answer 1

1

try doing:

import foo
print(foo.__file__)

with the folder structure you show I'd expect the result to be something like:

.../foo.py

But when you add an __init__.py to the foo folder it would instead be:

.../foo/__init__.py

with python packages you cannot actually import a folder so what ends up happening is that you import the __init__.py file from that folder instead of the foo.py so all you need to do is move the foo.py into the folder and rename it to __init__.py and you can then import foo or from foo import Foo the same way as you have it set up now.

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

2 Comments

Thanks -- this makes plenty of sense, and sounds much better than trying to manually merge two separate sets of definitions.
I really wish the documentation described what the __init__.py was actually for instead of just "init.py can just be an empty file, but it can also execute initialization code for the package or set the _all_ variable" the _init_.py file contains package level variables

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.