ATLAS Offline Software
Loading...
Searching...
No Matches
python.logging_bridge Namespace Reference

Functions

 install_printer (name="atlas")
 remove_printer ()

Variables

dict _LEVEL_MAP
str _DEFAULT_FORMAT = "%(tool)-25s%(levelname)-8s%(message)s"

Detailed Description

Bridge C++ message output to Python logging module.

Installs a callback that routes C++ IMessagePrinter output to a Python
logger named "atlas", integrating with standard logging configuration
(handlers, formatters, levels).

The bridge is installed automatically on package import with a default
StreamHandler and INFO level, so C++ messages are visible out of the box.
To suppress them::

    import logging
    logging.getLogger("atlas").setLevel(logging.WARNING)

To see DEBUG/VERBOSE messages::

    import logging
    logging.getLogger("atlas").setLevel(logging.DEBUG)

To customize the format, replace the default handler::

    import logging, sys
    logger = logging.getLogger("atlas")
    logger.handlers.clear()
    handler = logging.StreamHandler(sys.stderr)
    handler.setFormatter(logging.Formatter("[%(tool)s] %(levelname)s %(message)s"))
    logger.addHandler(handler)

Tool context is passed via the `extra` dict, so formatters can reference
`%(tool)s` to display the tool name.

In Athena/AthAnalysis builds (non-standalone), IMessagePrinter is not available
and the C++ bridge cannot be installed. The logger is still created and usable
for Python-side logging, but C++ messages will not be routed through it.

Function Documentation

◆ install_printer()

python.logging_bridge.install_printer ( name = "atlas")
Install a Python logger as the C++ message printer.

Routes all C++ IMessagePrinter messages (from tools, ASG framework, etc.)
to a Python logger with the given name. Called automatically by the package
on import with a default StreamHandler and INFO level, matching the C++
default stdout printer behaviour.

In Athena/AthAnalysis (non-standalone) builds, IMessagePrinter is not
available. The logger is still created and configured, but C++ messages
will not be routed through it.

Tool name is passed via the `extra` dict, so formatters can use `%(tool)s`.

Parameters
----------
name:
    Logger name (default: "atlas").

Returns
-------
logging.Logger
    The installed logger. Configure with handlers and setLevel as needed.

Notes
-----
Only one printer can be active at a time. Calling install_printer again
replaces the previous one. Call remove_printer() to restore default
stdout printing.

Cleanup is automatically registered via atexit, so you don't need to
call remove_printer() explicitly at interpreter shutdown.

Definition at line 65 of file logging_bridge.py.

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 # Add a default handler if none exists yet, so messages are visible
101 # out of the box without any user configuration.
102 if not logger.handlers:
103 handler = logging.StreamHandler(sys.stderr)
104 handler.setFormatter(logging.Formatter(_DEFAULT_FORMAT))
105 logger.addHandler(handler)
106
107 # Set level to INFO to match the C++ default MsgStream threshold, but
108 # only if the caller has not already configured a level (NOTSET means
109 # no explicit level was set yet).
110 if logger.level == logging.NOTSET:
111 logger.setLevel(logging.INFO)
112
113 # Don't propagate to the root logger — avoids double printing when
114 # the user has logging.basicConfig() or other root handlers configured.
115 logger.propagate = False
116
117 def printer_callback(level_int, tool_name, text):
118 """Callback invoked by C++ for each message."""
119 # Look up Python logging level for the C++ message level (int key)
120 py_level = _LEVEL_MAP.get(level_int, logging.INFO)
121 # Pass tool name via extra dict for formatter access
122 logger.log(py_level, text.rstrip(), extra={"tool": tool_name})
123
124 try:
125 set_python_printer(printer_callback)
126 # Ensure cleanup at interpreter shutdown
127 atexit.register(remove_printer)
128 except RuntimeError:
129 # Non-standalone (Athena/AthAnalysis) build: IMessagePrinter is not
130 # available. The logger is still usable for Python-side logging.
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

◆ remove_printer()

python.logging_bridge.remove_printer ( )
Remove the Python printer and restore default stdout printing.

Definition at line 139 of file logging_bridge.py.

139def remove_printer():
140 """Remove the Python printer and restore default stdout printing."""
141 set_python_printer() # Call with no arguments to reset

Variable Documentation

◆ _DEFAULT_FORMAT

str python.logging_bridge._DEFAULT_FORMAT = "%(tool)-25s%(levelname)-8s%(message)s"
protected

Definition at line 62 of file logging_bridge.py.

◆ _LEVEL_MAP

dict python.logging_bridge._LEVEL_MAP
protected
Initial value:
1= {
2 MsgLevel.NIL: logging.NOTSET,
3 MsgLevel.VERBOSE: logging.DEBUG - 5,
4 MsgLevel.DEBUG: logging.DEBUG,
5 MsgLevel.INFO: logging.INFO,
6 MsgLevel.WARNING: logging.WARNING,
7 MsgLevel.ERROR: logging.ERROR,
8 MsgLevel.FATAL: logging.CRITICAL,
9}

Definition at line 49 of file logging_bridge.py.