Recursive import within packages

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Stian Søiland

    Recursive import within packages


    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:
    [color=blue][color=green][color=darkred]
    >>> import blapp[/color][/color][/color]
    Blapp start
    Blupp start
    Blupp end
    Blapp end


    The same files with a directory thing with __init__:
    [color=blue][color=green][color=darkred]
    >>> from thing import blapp[/color][/color][/color]
    Blapp start
    Blupp start
    Blupp end
    Blapp end



    Changing the imports to import thing.blupp and import thing.blapp:
    [color=blue][color=green][color=darkred]
    >>> from thing import blapp[/color][/color][/color]
    Blapp start
    Blupp start
    Blupp end
    Blapp end



    Adding a print of the module with:

    print "Blapp end", blupp


    results in:
    [color=blue][color=green][color=darkred]
    >>> import blapp[/color][/color][/color]
    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

    [color=blue][color=green][color=darkred]
    >>> from thing import blapp[/color][/color][/color]
    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

    [color=blue][color=green][color=darkred]
    >>> from thing import blapp[/color][/color][/color]
    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)

    [color=blue][color=green][color=darkred]
    >>> from thing import blapp[/color][/color][/color]
    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"

    [color=blue][color=green][color=darkred]
    >>> import thing.blupp[/color][/color][/color]
    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.notexisti ng
    print "Blapp end", thing.blupp
    [color=blue][color=green][color=darkred]
    >>> from thing import blupp[/color][/color][/color]
    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.notexisti ng
    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.


    --
    Stian Søiland Being able to break security doesn't make
    Trondheim, Norway you a hacker more than being able to hotwire
    http://stain.portveien.to/ cars makes you an automotive engineer. [ESR]
Working...