Hands-on experience on Python logging
— 2 min read
Basic Usage
-
import logginglogging.basicConfig()logging.info("messages")
- What does
logging.basicConfig()
do? => creates a StreamHandler with a default Formatter and adding it to the root logger.
Concepts & Flow
- *LogRecord
- *Filter
- Formatter: different formatters for different handlers
- Handler
- StreamHandler
- FileHandler
- Logger
- can link to multiple (shared) handlers (many-to-many relation)
- has a manager
- See Logging Flow for details
-
Why designed in this way? The benefits ⇒ Flexibility
- Multiple Loggers arranged in a namespace hierarchy using dots as separators.
- When propagate is true, foo.bar logger will propagate the messages to its parent, the foo logger.
- Multiple destinations
The way I used it
- For simple projects/scripts, simply use the root logger, i.e. config via logging.basicConfig() and call logging.xxx("message")
- For packages/libraries, create logger under the package name, but do not add any handler by default. The idea is to let users to decide the way to log. If the package can be used via cli, then assign wanted handlers inside
__main__
. - For complex projects, create different handers based on our needs, and add them to the named loggers, e.g. current project name, third party packages, etc.
More Tips & Tricks
- Multiline formatter: see logging - how to indent multiline message printed by python logger? - Stack Overflow
- Log uncaught exceptions ⇒ Set sys.excepthook to a user-defined function with added friendly logs: see debugging - Using python's logging module to log all exceptions and errors - Stack Overflow
More Q&A
- How about logging in other programming languages?