Search code examples
pythonpython-3.xpython-importpython-modulecircular-reference

How to solve this Python import circular reference


I have a class JCheq, with a static var named 'logger'.

JCheq imports module printing_systems, but I need to use JCheq.logger from printing_systems.

My code does not compile after I put import JCheq in printing_systems.py.

jcheq.py

from printing_systems import printing_systems
from logger import logger

class JCheq:
    logger = logger.Logger('logs/jcheq.log', loglevel=logger.Logger.INFO)

    def __init__(self):
        pass
    ...

printing_systems/printing_systems.py

from jcheq import JCheq
class WinLPR:

    def __init__(self):
        pass

    @staticmethod
    def send(spool, params):
        temp_dir = tempfile.mkdtemp()
        try:
            JCheq.logger.log('Creando archivo temporal en dir: ' + temp_dir, logger.Logger.TRACE)

Error trace:

Traceback (most recent call last):
  File "/home/jsivil/Desktop/Proyectos/UNPAZ/jcheq/jcheq/jcheq.py", line 12, in <module>
    from printing_systems import printing_systems
  File "/home/jsivil/Desktop/Proyectos/UNPAZ/jcheq/jcheq/printing_systems/printing_systems.py", line 7, in <module>
    from jcheq import JCheq
  File "/home/jsivil/Desktop/Proyectos/UNPAZ/jcheq/jcheq/jcheq.py", line 12, in <module>
    from printing_systems import printing_systems
ImportError: cannot import name 'printing_systems'

Solution

  • Moving the import statement in the function is commonly used to solve circular imports. It is handy in cases when restructuring your application would be too costly (if useful at all).

    Another solution would be to move JCheq.logger into its own module that both jcheq.py and printing_systems/printing_systems.py would import.

    Or, you could make logger.Logger a factory function backed by some registry (or simply memoize it) so that it returns the same logger when the same arguments are given. This way, printing_system.py would simple import logger instead of importing jcheq.