如何配置Python logging使critical输出堆栈跟踪并终止程序?
logging.critical() Output Stack Traces and Exit Like Log4perl/SLF4J? Great question! Coming from Log4perl and SLF4J, it’s totally reasonable to expect critical-level logs to automatically include stack traces and terminate the program—Python’s built-in logging module is flexible but requires a bit of extra setup to match that behavior. Here are two solid approaches to get what you want:
1. Customize the Built-in logging Module
You can create a custom Logger subclass that overrides the critical method to automatically capture stack traces and exit the program. This lets you keep using the standard logging API while adding your desired behavior.
Example Implementation:
import logging import sys # Keep your custom exception if needed class GX8Exception(Exception): pass class CriticalExitLogger(logging.Logger): def critical(self, msg, *args, **kwargs): # Force stack trace capture by setting exc_info=True kwargs['exc_info'] = True # Let the parent class handle logging the message + trace super().critical(msg, *args, **kwargs) # Exit with your preferred status code sys.exit(-1) # Register the custom logger class so all new loggers use it logging.setLoggerClass(CriticalExitLogger) # Configure basic logging (adjust format/handlers to your needs) logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) # Get your logger instance log = logging.getLogger(__name__) # Now use log.critical directly, just like you wanted! # Example with your original message pattern: log.critical("--id=%s not found on --host=%s", "123", "example.com")
Notes:
exc_info=Truetells the logging module to include the current stack trace in the output.- This logs the trace from where
log.criticalis called. If you specifically need the trace from an exception raise point (like your original try/except code), you could modify thecriticalmethod to accept an optional exception instance and capture its traceback instead.
2. Use a Third-Party Logging Framework
If you don’t want to tweak the built-in module’s internals, third-party libraries like Loguru offer opinionated, out-of-the-box behavior that aligns closer with Log4perl/SLF4J.
Loguru Example:
from loguru import logger import sys # Add a filter to exit the program when a critical log is emitted def exit_on_critical(record): if record["level"].name == "CRITICAL": sys.exit(-1) # Configure Loguru to output full stack traces and apply the exit filter logger.add( sys.stderr, level="INFO", format="{time} - {name} - {level} - {message}", backtrace=True, # Enables full stack traces for errors diagnose=True, # Optional: includes variable values in traces filter=exit_on_critical ) # Use logger.critical directly logger.critical("--id={} not found on --host={}", "123", "example.com")
Why Loguru?
- It eliminates most boilerplate compared to the built-in
loggingmodule. backtrace=Trueautomatically captures stack traces for error-level logs.- The filter system makes it easy to add custom behavior like exiting on critical logs.
Bonus: Lightweight Wrapper Function
If subclassing feels overkill, a simple wrapper works too:
import logging import sys log = logging.getLogger(__name__) def critical_exit(msg, *args, **kwargs): log.critical(msg, *args, exc_info=True, **kwargs) sys.exit(-1) # Usage: critical_exit("--id=%s not found on --host=%s", "123", "example.com")
All of these approaches let you avoid repetitive try/except blocks while getting the stack trace + exit behavior you’re used to from Log4perl and SLF4J.
内容的提问来源于stack exchange,提问作者MortenB

