Circular import hell

Python is an extremely elegant language. Well, except ... except for imports. I still cannot get it to work as it seems natural to me.

I have a class MyObjectA , which is located in the file mypackage/myobjecta.py . This object uses some utility functions that are located in mypackage/utils.py . Therefore, in my first lines in myobjecta.py I write:

 from mypackage.utils import util_func1, util_func2 

But some utility functions create and return new instances of MyObjectA . So I need to write in utils.py :

 from mypackage.myobjecta import MyObjectA 

Well, I can’t. This is circular import, and Python will refuse to do so.

There are many questions regarding this problem, but no one gives a satisfactory answer. From what I can read in all the answers:

  • Reorganize your modules, you are doing it wrong! But I don’t know how to better organize my modules even in such a simple case as I presented.
  • Try just import ... rather than from ... import ... (I personally hate writing and potentially reorganizing all classifiers of names; I like to see what exactly I enter into the module from the outside world). Will this help? I am not sure there is still circular imports.
  • To do hacks as importing something in the inner area of ​​the function body with only one line before using something from another module.

I still hope that there is a solution number 4) that would be Pythonic in terms of functionality, elegance and simplicity and work. Or not?

Note. I am primarily a C ++ programmer, the above example is so easily solved by including the appropriate headers, which I cannot believe that this is not possible in Python.

+6
source share
3 answers

Nothing prevents importing something into the body of the function, this is an absolutely correct template:

 def some_function(): import logging do_some_logging() 

Typically, an ImportError occurs only because import() evaluates the top-level operators of the entire file when called.

Unless you have a logical circular dependency ... nothing is impossible in python ...

There is a way around this if you really want your import to be on top :

David Beazleys has a great conversation Modules and packages: Live and Let Die! - PyCon 2015 , 1:54:00 , here is a way to work with circular import in python:

 try: from images.serializers import SimplifiedImageSerializer except ImportError: import sys SimplifiedImageSerializer = sys.modules[__package__ + '.SimplifiedImageSerializer'] 

This is trying to import the SimplifiedImageSerializer , and if ImportError raised because it is already imported, it will pull it out of importcache.

PS: You have to read this whole post in David Baisley's voice.

0
source

Do not import mypackage.utils into your main module, it already exists in mypackage.myobjecta . After importing mypackage.myobjecta , the code from this module is executed, and you do not need to import anything into your current module, because mypackage.myobjecta already complete.

0
source

The way I got around in my (first) project was to simply copy and paste the entire module into the body of another and use only one import. Code duplication is inelegant, but it allowed me to move on.

0
source

All Articles