On Tue, May 10, 2016 at 9:54 AM, Brendan Abel <007bren...@gmail.com> wrote: > Consider the following example python package where `a.py` and `b.py` > depend on each other: > > /package > __init__.py > a.py > b.py > > > There are several ways I could import the "a.py" module in "b.py" > > import package.a # Absolute import > import package.a as a_mod # Absolute import bound to different name > from package import a # Alternate absolute import > import a # Implicit relative import (deprecated, py2 > only) > from . import a # Explicit relative import > > Unfortunately, only the 1st and 4th syntax actually work when you have > circular dependencies (the rest all raise `ImportError` or > `AttributeError`), and the 4th syntax only works in python 2 and is > generally discouraged because of the possibility of name conflicts.
The fifth is the one that I would recommend. Can you give an example of a circular dependency that makes it fail? Here's the trivial case that I tried: rosuav@sikorsky:~/tmp$ mkdir package rosuav@sikorsky:~/tmp$ touch package/__init__.py rosuav@sikorsky:~/tmp$ cat >package/a.py from . import b def func_a(x): print("func_a: %d" % x) if x % 2: b.func_b(x-1) rosuav@sikorsky:~/tmp$ cat >package/b.py from . import a def func_b(x): print("func_b: %d" % x) if x % 2: a.func_a(x-1) rosuav@sikorsky:~/tmp$ python3 Python 3.6.0a0 (default:98678738b7e9, May 2 2016, 13:37:04) [GCC 5.3.1 20160409] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import package.a >>> package.a.func_a(5) func_a: 5 func_b: 4 >>> import package.b >>> package.b.func_b(5) func_b: 5 func_a: 4 >>> The imports work fine as long as you use strictly "from . import modulename", and not "from .modulename import objectname". Circular imports of the latter form will indeed fail, but if you have non-circular imports, you can stop them from failing by forcing module load order: rosuav@sikorsky:~/tmp$ cat package/a.py from .b import func_b def func_a(x): print("func_a: %d" % x) if x % 2: func_b(x-1) rosuav@sikorsky:~/tmp$ cat >package/__init__.py from . import a from . import b This does prevent lazy loading, though, so if your circular imports are in an optional part of the package (and one that takes a long time to load), you might want to consider setting it up some other way. ChrisA -- https://mail.python.org/mailman/listinfo/python-list