65def install_printer(name="atlas"):
66 """Install a Python logger as the C++ message printer.
67
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.
72
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.
76
77 Tool name is passed via the `extra` dict, so formatters can use `%(tool)s`.
78
79 Parameters
80 ----------
81 name:
82 Logger name (default: "atlas").
83
84 Returns
85 -------
86 logging.Logger
87 The installed logger. Configure with handlers and setLevel as needed.
88
89 Notes
90 -----
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
93 stdout printing.
94
95 Cleanup is automatically registered via atexit, so you don't need to
96 call remove_printer() explicitly at interpreter shutdown.
97 """
98 logger = logging.getLogger(name)
99
100
101
102 if not logger.handlers:
103 handler = logging.StreamHandler(sys.stderr)
104 handler.setFormatter(logging.Formatter(_DEFAULT_FORMAT))
105 logger.addHandler(handler)
106
107
108
109
110 if logger.level == logging.NOTSET:
111 logger.setLevel(logging.INFO)
112
113
114
115 logger.propagate = False
116
117 def printer_callback(level_int, tool_name, text):
118 """Callback invoked by C++ for each message."""
119
120 py_level = _LEVEL_MAP.get(level_int, logging.INFO)
121
122 logger.log(py_level, text.rstrip(), extra={"tool": tool_name})
123
124 try:
125 set_python_printer(printer_callback)
126
127 atexit.register(remove_printer)
128 except RuntimeError:
129
130
131 logger.debug(
132 "C++ message bridge unavailable (not a standalone build); "
133 "C++ tool messages will not be routed through Python logging."
134 )
135
136 return logger
137
138