To begin with: Your motivation for using namespace packages is flawed. There's nothing wrong with empty __init__.py
files; they might be empty now but later can be filled with content. Even if they stay empty that doesn't cause any trouble.
Having said that, technically there's nothing wrong with putting a namespace package inside a regular package. When you perform an import of the form import a.b.c
then each component is resolved separately and b
can be a namespace package that lives inside a regular package a
. Consider the following directory layout:
.
└── a
├── b
│ └── c.py
└── __init__.py
Then you can import the module c
:
>>> import a.b.c
>>> a
<module 'a' from '/tmp/a/__init__.py'>
>>> a.b
<module 'a.b' (namespace)>
>>> a.b.c
<module 'a.b.c' from '/tmp/a/b/c.py'>
As you can see all components are instantiated individually where the namespace a.b
's __file__
attribute is set to None
.
However this setup prevents the main purpose of namespace packages, namely that they can be split over multiple directories. This is because even though b
is a namespace package, it lives inside the regular package a
which will be cached in sys.modules
and thus prevents the import path from being searched any further. As an example consider the following directory layout:
.
├── dir1
│ └── parent
│ ├── child
│ │ ├── one.py
│ ├── __init__.py
├── dir2
│ └── parent
│ ├── child
│ │ └── two.py
│ └── __init__.py
└── main.py
There are two namespace packages dir1/parent/child
and dir2/parent/child
. However you can only use one of them, since the regular package dir1/parent
prevents access to the other. Let's try the following content for main.py
:
import sys
sys.path.extend(('dir1', 'dir2'))
import parent.child.one # this works
print(sys.modules['parent'])
print(sys.modules['parent.child'])
print(sys.modules['parent.child.one'])
import parent.child.two # this fails
print(sys.modules['parent.child.two'])
and we'll get the following output:
<module 'parent' from 'dir1/parent/__init__.py'>
<module 'parent.child' (namespace)>
<module 'parent.child.one' from 'dir1/parent/child/one.py'>
Traceback (most recent call last):
File "main.py", line 11, in <module>
import parent.child.two
ModuleNotFoundError: No module named 'parent.child.two'
This is because sys.modules['parent']
is a regular package and thus in import parent.child.two
the parent
component is resolved to that very package, which does have an attribute child
but this namespace doesn't contain two
. A further search on the import path would be required to find that module.
Removing the two __init__.py
files from the above folder structure turns the two regular packages into namespace packages and the above script will work (i.e. import parent.child.two
succeeds):
<module 'parent' (namespace)>
<module 'parent.child' (namespace)>
<module 'parent.child.one' from 'dir1/parent/child/one.py'>
<module 'parent.child.two' from 'dir2/parent/child/two.py'>
To answer your questions specifically:
1) You can have .py
files at any level of a namespace package hierarchy. So long as it doesn't contain an __init__.py
file, it's considered a namespace package and its contents are resolved accordingly. Consider the following directory layout:
.
└── a
├── b
│ ├── c
│ │ └── three.py
│ └── two.py
└── one.py
You can import any of the modules inside any of the namespace packages:
>>> import a.one
>>> import a.b.two
>>> import a.b.c.three
>>> a.b.c
<module 'a.b.c' (namespace)>
2) As detailed above, you can place namespace packages inside regular packages but it doesn't make much sense, since it prevents their intended usage.
3) This depends very much on what you mean by "should". Technically the __init__.py
is not required, but it definitely makes a lot of sense.
As noted in the beginning, __init__.py
files have a purpose beyond indicating regular python packages, and often they get filled with content too. If not, this is nothing to worry about.