Search code examples
pythonimportcircular-dependency

Making a module partially imported


I have a package with a couple of modules config, and logging (amongst others).

The logging module provides a method to log to the package's log file (which is defined in the config module).

The config module contains a bunch of static config values (hardcoded) as well as some dynamic ones loaded from a file.

mypackage/logging.py

import mypackage.config

def log(message):
    log_file = mypackage.config.log_file
    open(log_file, "a").write(message + "\n")

mypackage/config.py

import mypackage.logging

log_file = "/var/log/mypackage.log"

try:
    # Load some more config from file.
except Exception as e:
    # That's fine, just log that we couldn't open the file.
    mypackage.logging.log("Couldn't open config file: %s" % str(e))

The problem is that the above code suffers from a circular dependency problem, where calling mypackage.logging.log() from mypackage/config.py before it has finished importing means that the log_file = mypackage.config.log_file line in mypackage/logging.py will fail.

Is it possible to import the static portion of mypackage/config.py into the module so that is available at mypackage.config.log_file when mypackage.logging.log() is called?

Failing that, is there a neater way I can design this without this problem?


Solution

  • To make your current code work you can import config.log_file in log function:

    def log(message):
        from mypackage.config import log_file
        open(log_file, "a").write(message + "\n")
    

    Of course, you have a lot of possibilities to redesign the whole system. For instance, you can put all settings which can produce a circular dependency into their own config file and import it from both logging.py and config.py.