44from ColumnarToolWrapperPython.python_tool_handle
import set_python_printer, MsgLevel
66 """Install a Python logger as the C++ message printer.
68 Routes all C++ IMessagePrinter messages (from tools, ASG framework, etc.)
69 to a Python logger with the given name. Called automatically by the package
70 on import with a default StreamHandler and INFO level, matching the C++
71 default stdout printer behaviour.
73 In Athena/AthAnalysis (non-standalone) builds, IMessagePrinter is not
74 available. The logger is still created and configured, but C++ messages
75 will not be routed through it.
77 Tool name is passed via the `extra` dict, so formatters can use `%(tool)s`.
82 Logger name (default: "atlas").
87 The installed logger. Configure with handlers and setLevel as needed.
91 Only one printer can be active at a time. Calling install_printer again
92 replaces the previous one. Call remove_printer() to restore default
95 Cleanup is automatically registered via atexit, so you don't need to
96 call remove_printer() explicitly at interpreter shutdown.
98 logger = logging.getLogger(name)
102 if not logger.handlers:
103 handler = logging.StreamHandler(sys.stderr)
104 handler.setFormatter(logging.Formatter(_DEFAULT_FORMAT))
105 logger.addHandler(handler)
110 if logger.level == logging.NOTSET:
111 logger.setLevel(logging.INFO)
115 logger.propagate =
False
117 def printer_callback(level_int, tool_name, text):
118 """Callback invoked by C++ for each message."""
120 py_level = _LEVEL_MAP.get(level_int, logging.INFO)
122 logger.log(py_level, text.rstrip(), extra={
"tool": tool_name})
125 set_python_printer(printer_callback)
127 atexit.register(remove_printer)
132 "C++ message bridge unavailable (not a standalone build); "
133 "C++ tool messages will not be routed through Python logging."