Hey I was wondering how to implement a global logger that could be used everywhere with your own settings:
I have
class customLogger(logging.Logger):
...
in a file with its formatters and other stuff. The logger works perfectly on its own.
I import this module in my main.py file and create an object like this:
self.log = log.customLogger(arguments)
But obviously i cannot access this object from other parts of my code. Am i using a wrong approach? Is there a better way to do this?
Create an instance of
customLogger
in your log module and use it as a singleton - just use the imported instance, rather than the class.Use
logging.getLogger(name)
to create a named global logger.main.py
log.py
submodule.py
Output
You can just pass it a string with a common sub-string before the first period. The parts of the string separated by the period (".") can be used for different classes / modules / files / etc. Like so (specifically the
logger = logging.getLogger(loggerName)
part):Since I haven't found a satisfactory answer, I would like to elaborate on the answer to the question a little bit in order to give some insight into the workings and intents of the
logging
library, that comes with Python's standard library.In contrast to the approach of the OP (original poster) the library clearly separates the interface to the logger and configuration of the logger itself.
That means you should not create a custom logger class and configure the logger inside that class by adding any configuration or whatsoever.
The
logging
library introduces four components: loggers, handlers, filters, and formatters.A common project structure looks like this:
Inside your code (like in module.py) you refer to the logger instance of your module to log the events at their specific levels.
The special variable
__name__
refers to your module's name and looks something likeproject.package.module
depending on your application's code structure.module.py (and any other class) could essentially look like this:
The logger in each module will propagate any event to the parent logger which in return passes the information to its attached handler! Analogously to the python package/module structure, the parent logger is determined by the namespace using "dotted module names". That's why it makes sense to initialize the logger with the special
__name__
variable (in the example above name matches the string "project.package.module").There are two options to configure the logger globally:
Instantiate a logger in project.py with the name
__package__
which equals "project" in this example and is therefore the parent logger of the loggers of all submodules. It is only necessary to add an appropriate handler and formatter to this logger.Set up a logger with a handler and formatter in the executing script (like main.py) with the name of the topmost package.
The executing script, like main.py for example, might finally look something like this:
The method call
log.setLevel(...)
specifies the lowest-severity log message a logger will handle but not necessarily output! It simply means the message is passed to the handler as long as the message's severity level is higher than (or equal to) the one that is set. But the handler is responsible for handling the log message (by printing or storing it for example).Hence the
logging
library offers a structured and modular approach which just needs to be exploited according to one's needs.Logging documentation