erikbstack
erikbstack

Reputation: 13254

Importing "sub" modules to be own "sub" modules

Assume you have a package foo with the following __init__.py:

from bar import *

With bar being any python module installed with pip install bar.

Now what always works when you can import bar:

from bar import submodule #works
import bar.submodule      #works, too

Now I would assume the following things would all work as well:

from foo import submodule     # a) is possible
import foo.submodule          # b) not possible ("no module named submodule")
from foo.bar import submodule # c) also impossible ("no module named submodule")

Why are they not possible? What would I need to do to make them possible, from the point of view of the foo maintainer?

Upvotes: 2

Views: 84

Answers (1)

Silas Ray
Silas Ray

Reputation: 26160

submodule and bar are members of the foo module object, not submodules of it. Therefore, they behave just like any other member attribute of foo. You can bring them into the module namespace of a third module with the from foo import ... form, but you can't directly import them relative to foo. I guess you could if you hacked them in to sys.modules under the desired name manually, but you really shouldn't be doing anything like that...

To illustrate the issue:

foo.py

# x and y are values in the foo namespace, available as member attributes
# of the foo module object when foo is imported elsewhere
x = 'x'
y = 'y'

bar.py

# the foo module object is added as a member attribute of bar on import
# with the name foo in the bar namespace
import foo
# the same foo object is aliased within the bar namespace with the name
# fooy
import foo as fooy
# foo.x and foo.y are referenced from the bar namespace as x and y,
# available as member attributes of the bar module object
from foo import x, y
# z is a member attribute of the bar module object
z = 'z'

baz.py

# brings a reference to the x, y, and z attributes of bar (x and y
# come in turn from foo, though that's not relevant to the import;
# it just cares that bar has x, y, and z attributes), in to the
# namespace of baz
from bar import x, y, z
# won't work, because foo is a member of bar, not a submodule
import bar.foo
# will work, for the same reason that importing x, y, and z work
from bar import foo

Upvotes: 2

Related Questions