Recursive import within packages

  • Thread starter Stian =?iso-8859-1?Q?S=F8iland?=
  • Start date
S

Stian =?iso-8859-1?Q?S=F8iland?=

all examples performed with:

Python 2.3+ (#2, Aug 10 2003, 11:09:33)
[GCC 3.3.1 20030728 (Debian prerelease)] on linux2
(2, 3, 0, 'final', 1)



This is a recursive import:

-- blapp.py --
print "Blapp start"
import blupp
print "Blapp end"

-- blupp.py --
print "Blupp start"
import blapp
print "Blupp end"


This works like a charm:
Blapp start
Blupp start
Blupp end
Blapp end


The same files with a directory thing with __init__:
Blapp start
Blupp start
Blupp end
Blapp end



Changing the imports to import thing.blupp and import thing.blapp:
Blapp start
Blupp start
Blupp end
Blapp end



Adding a print of the module with:

print "Blapp end", blupp


results in:
Blapp start
Blupp start
Blupp end <module 'blapp' from 'blapp.py'>
Blapp end <module 'blupp' from 'blupp.py'>




Changing to:

import thing.blapp as blapp

and vice versa

Blapp start
Blupp start
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "thing/blapp.py", line 2, in ?
import thing.blupp as blupp
File "thing/blupp.py", line 2, in ?
import thing.blapp as blapp
AttributeError: 'module' object has no attribute 'blapp'



Changing to:

from thing import blapp

and vice versa

Blapp start
Blupp start
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "thing/blapp.py", line 2, in ?
from thing.blupp import blupp
File "thing/blupp.py", line 2, in ?
from thing import blapp
ImportError: cannot import name blapp




And finally:

print "Blapp start"
import thing.blupp
print "Blapp end", thing.blupp


(and vice versa)

Blapp start
Blupp start
Blupp end
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "thing/blapp.py", line 2, in ?
import thing.blupp
File "thing/blupp.py", line 3, in ?
print "Blupp end", thing.blapp
AttributeError: 'module' object has no attribute 'blapp'


Adding a print of dir(thing) verifies this:

-- blapp.py -- (and vice versa)
print "Blapp start"
import thing.blupp
print dir(thing)
print "Blapp end"

Blupp start
Blapp start
['__builtins__', '__doc__', '__file__', '__name__', '__path__']
Blapp end
['__builtins__', '__doc__', '__file__', '__name__', '__path__', 'blapp']
Blupp end



-- blapp.py --

print "Blapp start"
import thing.blupp
import thing.notexisting
print "Blapp end", thing.blupp
Blupp start
Blapp start
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "thing/blupp.py", line 2, in ?
import thing.blapp
File "thing/blapp.py", line 3, in ?
import thing.notexisting
ImportError: No module named notexisting



Now, could anyone please explain to me the logic involved here?

Why is circular import only valid when accessing them without package
name? It clearly works by not using full references, even to print the
module while the other module is being loaded.

The user-fix to the problem is of course:

a) Don't use circular references
b) delay circular import until module usage
(ie. within class/function)
c) Use relative modulenames (works only within the same package)
d) import thing.blapp - but don't expect thing.blapp to be there
until module usage (ie. within class/function)


But my question is why this works outside packages, but not inside
packages. This must be a bug, but I can't find it anywhere in the bugs
section on SourceForge.

(A google search for 'circular import' on Google seems impossible =) Way
too many circle-square-shape-examples!)

The FAQ says:

Circular imports are fine where both modules use the "import <module>"
form of import. They fail when the 2nd module wants to grab a name
out of the first ("from module import name") and the import is at
the top level. That's because names in the 1st are not yet available,
(the first module is busy importing the 2nd).

However that is not correct in this case, the "thing" module is loaded
and works fine, it is the name thing.blapp that is not registered until
after blapp is loaded. In my opinion thing.blapp should be bound before
the actuall import of thing.blapp.

Actually, thing.blapp gets registered into sys.modules right away.
 

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,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top