I've been trying to figure out how best to set this up. Cutting it down as much as I can. I have 4 python files: core.py (main), logger_controler.py, config_controller.py, and a 4th as a module or singleton well just call it tool.py.
The way I have it setup is logging has an init function that setup pythons built in logging with the necessary levels, formatter, directory location, etc. I call this init function in main.
import loggingimport logger_controllerdef main(): logger_controller.init_log() logger = logging.getLogger(__name__)if __name__ == "__main__": main()
config_controller is using configparser and is mainly a singleton as a controller for my config.
import configparserimport logginglogger = logging.getLogger(__name__)class ConfigController(object): def __init__(self, *file_names): self.config_parser = configparser.ConfigParser() found_files = self.config_parser.read(file_names) if not found_files: raise ValueError("No config file found.") self._validate() def _validate(self): ... def read_config(self, section, field): try: data = self.config_parser.get(section, field) except (configparser.NoSectionError, configparser.NoOptionError) as e: logger.error(e) data = None return dataconfig = ConfigController("config.ini")
And then my problem is trying to create the 4th file and making sure both my logger and config parser are running before it. I'm also wanting this 4th one to be a singleton so it's following a similar format as the config_controller.
So tool.py uses config_controller to pull anything it needs from the config file. It also has some error checking for if config_controller's read_config returns None as that isn't validated in _validate. I did this as I wanted my logging to have a general layer for error checking and a more specific layer. So _validate just checks if required fields and sections are in the config file. Then wherever the field is read will handle extra error checking.
So my main problem is this:How do I have it where my logger and configparser are both running and available before anything else. I'm very much willing to rework all of this, but I'd like to keep the functionality of it all.
One attempt I tried that works, but seems very messy is making my logger_controler a singleton that just returns python's logging object.
import loggingimport osclass MyLogger(object): def __new__(cls, *args, **kwargs): init_log() return loggingdef init_log(): ...mylogger = MyLogger()
Then in core.py
from logger_controller import myloggerlogger = mylogger.getLogger(__name__)
I feel like there should be a better way to do the above, but I'm honestly not sure how.
A few ideas:
- Would I be able to extend the logging class instead of just using that init_log function?
- Maybe there's a way I can make all 3 individual modules such that they each initialize in a correct order? My attempts here didn't quite work as I also have some internal data that I wouldn't want exposed to classes using the module, just the functionality.
- I'd like to have it where all 3, logging, configparsing, and the tool, available anywhere I import them.
- How I have it setup now "works" but if I were to import the tool.py anywhere in core.py and an error occurs that I need to catch, then my logger won't be able to log it as this tool is loading before the init of my logger.