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: >>> import blapp Blapp start Blupp start Blupp end Blapp end The same files with a directory thing with __init__: >>> from thing import blapp Blapp start Blupp start Blupp end Blapp end Changing the imports to import thing.blupp and import thing.blapp: >>> from thing import blapp Blapp start Blupp start Blupp end Blapp end Adding a print of the module with: print "Blapp end", blupp results in: >>> import blapp 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 >>> from thing import blapp 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 >>> from thing import blapp 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) >>> from thing import blapp 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" >>> import thing.blupp 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 >>> from thing import 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. -- 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]
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4