'Python conditional 'module object has no attribute' error with personal package distinct from circular import issue

I'm getting a 'module object has no attribute ..." error when trying to use a package heirarchy I created. The error is reminiscant of the error you get when there is a circular import (i.e. module a imports b and module b imports a), but I can't see that issue here. I've gone through many posts with a similar error, but none of the explanations I saw quite fit.

This was seen with python 2.7.1 and python 2.4.3.

I've watered it down to the following example:

Consider the following heirarchy (see code below):

alpha
alpha/__init__.py
alpha/bravo
alpha/bravo/__init__.py
alpha/bravo/charlie.py
alpha/bravo/delta.py
alpha/bravo/echo.py

The module charlie imports echo which in turn imports delta. If the alpha/bravo/__init__.py (like alpha/__init__.py) is essentially blank, a script can do:

import alpha.bravo.charlie

The problem surfaces if I try to import alpha.bravo.charlie in alpha/bravo/__init__.py (with the thinking I could surface relevant classes/methods there, and a script would do 'import alpha.bravo').

Code:

alpha/__init__.py

(blank)

alpha/bravo/__init__.py

import alpha.bravo.charlie

alpha/bravo/charlie.py

import alpha.bravo.echo
def charlie_foo(x): return str(x)
def charlie_bar(x): return alpha.bravo.echo.echo_biz()

alpha/bravo/delta.py

def delta_foo(x): return str(x)

alpha/bravo/echo.py

import alpha.bravo.delta
print alpha.bravo.delta.delta_foo(1)
def echo_biz(): return 'blah'

If I try:

python -c 'import alpha.bravo'

I get:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/kmkc980/svn/working/azcif/python/lib/alpha/bravo/__init__.py", line 1, in <module>
    import alpha.bravo.charlie
  File "/home/kmkc980/svn/working/azcif/python/lib/alpha/bravo/charlie.py", line 1, in <module>
    import alpha.bravo.echo
  File "/home/kmkc980/svn/working/azcif/python/lib/alpha/bravo/echo.py", line 2, in <module>
    print alpha.bravo.delta.delta_foo(1)
AttributeError: 'module' object has no attribute 'bravo'

But, if I comment out the import line in alpha/bravo/__init__.py, then all seems OK:

python -c 'import alpha.bravo'

python -c 'import alpha.bravo.charlie'
1

Moreover, if I use the same code above (including the import line in alpha/bravo/__init__.py), but edit everything to exclude the 'alpha' level of the hierarchy, it seems to work fine.

So the hierarchy is now just:

bravo
bravo/__init__.py
bravo/charlie.py
bravo/delta.py
bravo/echo.py

and I change all the lines with "alpha.bravo.*" to "bravo.*"

Then no problem:

python -c 'import bravo'
1

I've been able to work around the issue, but I'd still like to understand it. Thanks.



Solution 1:[1]

Instead of using absolute imports, it might help to use relatives.

i.e.

alpha/bravo/_init_.py

import alpha.bravo.charlie

should be

import charlie

Otherwise, it probably is a circular import. i.e. if you import alpha.bravo.charlie from charlie, that means

alpha/__init__.py
bravo/__init__.py
charlie/__init__.py 

All are loaded (or rather, prevented from doing so since they're already loaded). That might cause the problem you're seeing.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 synthesizerpatel