confusion about package/module imports

J

Jugdish

Why doesn't the following work?
$HOME/pkg/__init__.py
$HOME/pkg/subpkg/__init__.py
$HOME/pkg/subpkg/a.py
$HOME/pkg/subpkg/b.py
# empty
import a
import b
class A:
pass
import pkg.subpkg.a
class B(pkg.subpkg.a.A):
pass
Traceback (most recent call last):
File "pkg/subpkg/b.py", line 1, in ?
import pkg.subpkg.a
File "$HOME/pkg/subpkg/__init__.py", line 2, in ?
import b
File "$HOME/pkg/subpkg/b.py", line 2, in ?
class B(pkg.subpkg.a.A):
AttributeError: 'module' object has no attribute 'subpkg'
 
S

Scott David Daniels

Jugdish said:
Why doesn't the following work?
...
[well boiled-down code skipped]
Traceback (most recent call last):
File "pkg/subpkg/b.py", line 1, in ?
import pkg.subpkg.a
File "$HOME/pkg/subpkg/__init__.py", line 2, in ?
import b
File "$HOME/pkg/subpkg/b.py", line 2, in ?
class B(pkg.subpkg.a.A):
AttributeError: 'module' object has no attribute 'subpkg'

OK, here's a trick for finding import problems:
python -v <file to fiddle>
(shows all imports)

And for this case:
sprinkle prints to find out what is happening.

so, add "print __name, __file__" to the top of each file where
you wonder what is going on.
I later added prints in pkg/subpkg/__init__.py to make the steps clear.

You'll see that b is executed (making module __main__),
it imports pkg.subpkg.a,
which is accomplished by importing pkg (successfully),
then by importing pkg.subpkg
which imports pkg.subpkg.a (successfully)
and then imports pkg.subpkg.b
which then attempts to import pkg.subpkg.a
At that point, only the module pkg
and what should eventually become pkg.subpkg.a
have been successfully imported. pkg.subpkg had not yet been imported.
If you remove the "import b" from subpkg's __init__, you will find
your problems going away.
Alternatively, you can remove the import a / import b from subpkg
and add import subpkg.a, subpkg.b to pkg's __init__. Essentially,
you need pkg.subpkg fully imported before you import pkg.subpkg.b

Of course, in most of these cases you will have imported the code
for b twice, once as a main program, and once as a module in the
hierarchy, which is probably your actual problem (and why I use
"print __name__, __file__").


--Scott David Daniels
(e-mail address removed)
 
J

Jugdish

Thanks very much for your helpful response!
You'll see that b is executed (making module __main__),
(1) it imports pkg.subpkg.a,
(2) which is accomplished by importing pkg (successfully),
(3) then by importing pkg.subpkg
(4) which imports pkg.subpkg.a (successfully)
(5) and then imports pkg.subpkg.b
(6) which then attempts to import pkg.subpkg.a

What I'm not really understanding here is why this fails at lines (5)
and (6). If pkg.subpkg.a has already been successfully imported at
line (4), then (6) should be detected as a duplicate import and just
be skipped, right? So the import at line (5) should succeed.
 
S

Scott David Daniels

Jugdish said:
Thanks very much for your helpful response!


What I'm not really understanding here is why this fails at lines (5)
and (6). If pkg.subpkg.a has already been successfully imported at
line (4), then (6) should be detected as a duplicate import and just
be skipped, right? So the import at line (5) should succeed.

I'm sorry, I used shorthand. While a module is being imported,
it only provisionally has a name. Until subpkg is fully imported,
there is no module named pkg.subpkg. At the root level (pkg, for
example), the module is provisionally added. Further down the tree,
the module (such as that for pkg/subpkg/__init__.py) is only added
to the symbol table (the packages __dict__) when the module has been
completely imported.

-Scott
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top