Guest User

Untitled

a guest
Jan 24th, 2017
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.12 KB | None | 0 0
  1. # When are Python circular imports fatal?
  2.  
  3. In your Python package, you have:
  4. - an `__init__.py` that designates this as a Python package
  5. - a `module_a.py`, containing a function `action_a()` that references an attribute (like a function or variable) in `module_b.py`, and
  6. - a `module_b.py`, containing a function `action_b()` that references an attribute (like a function or variable) in `module_a.py`.
  7.  
  8. This situation can introduce a **circular import error**: `module_a` attempts to import `module_b`, but can't, because `module_b` needs to import `module_a`, which is in the process of being interpreted.
  9.  
  10. But, sometimes Python is magic, and code that looks like it should cause this circular import error works just fine!
  11.  
  12. When does it work and when does it not? *Why* does it work when it does?
  13.  
  14. ## When it works
  15.  
  16. ### Top of module; no `from`; Python 2 only
  17.  
  18. Imports at top of module. `import MODULE`. Function references MODULE.ATTRIBUTE. Since `import MODULE` is an implicit relative import from the current directory, this might not work for importing from other packages. Since `import MODULE` is a **syntax error in Python 3** this **works in Python 2 only** so is not future-proof.
  19.  
  20. # pkg/module_a.py # pkg/module_b.py
  21. import module_b import module_a
  22. def action_a(): def action_b():
  23. print(module_b.action_b.__name__) print(module_a.action_a.__name__)
  24.  
  25. ### Top of module; no `from`; no relative
  26.  
  27. Imports at top of module. `import PACKAGE.MODULE`. Function references PACKAGE.MODULE.ATTRIBUTE. Since `import .MODULE` is a syntax error, relative imports can't be used here; modules must know their containing package's name.
  28.  
  29. # pkg/module_a.py # pkg/module_b.py
  30. import pkg.module_b import pkg.module_a
  31. def action_a(): def action_b():
  32. print(pkg.module_b.action_b.__name__) print(pkg.module_a.action_a.__name__)
  33.  
  34. ### Bottom of module; import attribute, not module; `from` okay.
  35.  
  36. Imports at bottom of module (or at least after referenced attribute). `from PACKAGE.MODULE import ATTRIBUTE`. May be relative, like `from .MODULE import ATTRIBUTE`. Function references ATTRIBUTE.
  37.  
  38. # pkg/module_a.py # pkg/module_b.py
  39. def action_a(): def action_b():
  40. print(action_b.__name__) print(action_a.__name__)
  41. from .module_b import action_b from .module_a import action_a
  42.  
  43. ### Top of function; `from` okay
  44.  
  45. Imports at top of **function**. `from PACKAGE import MODULE`. PACKAGE may be relative, like `.`. Function references MODULE.ATTRIBUTE. This becomes ugly (but still works) if you have several functions that all refer to the same MODULE.
  46.  
  47. # pkg/module_a.py # pkg/module_b.py
  48. def action_a(): def action_b():
  49. from . import module_b from . import module_a
  50. print(module_b.action_b.__name__) print(module_a.action_a.__name__)
Add Comment
Please, Sign In to add comment