Warnings
A warning can be raised similar to an exception, but it doesn’t interrupt execution at the position where it was
raised. The warning travels upwards the call-stack until it’s handled by a WarningCollector
similar to a try .. except statement. A warning nobody collects is dropped; a
CriticalWarning or an exception nobody collects raises an
UnhandledCriticalWarningError or UnhandledExceptionError.
A warning is raised by Calling the class-method WarningCollector.Raise.
This function expects a single parameter: an instance of Warning.
To handle a raised warning, a with-statement is used to collect raised warnings. Usually, a list is handed over
to a WarningCollector context.
from pyTooling.Warning import WarningCollector
class ClassA:
def methA_RaiseException(self) -> None:
WarningCollector.Raise(Warning("Warning from ClassA.methA_RaiseException"))
from pyTooling.Warning import WarningCollector
class Caller:
def operation(self) -> None:
warnings = []
a = ClassA()
with WarningCollector(warnings) as warning:
a.methA_RaiseException()
print("Warnings:)
for warning in warnings:
print(f" {warning}")
Competing Solutions
Python’s own warnings let execution continue too, but what happens to a warning is configured for the whole process.
WarningCollector.Raise hands a warning to the innermost
WarningCollector of the current thread, which keeps it in a list, and its handler decides
per warning whether it is escalated - so the caller of an operation decides.
warnings
Source: warnings of Python’s standard library.
Disadvantages
What happens to a warning is decided by a global list of filters, matched by message, category, module and line - e.g.
-W errorturns every warning into an exception, for the whole process.catch_warningschanges the module’s global state, which isn’t safe with several threads or coroutines - unless the flagsys.flags.context_aware_warningsis set, which Python 3.14 sets by default only in its free-threaded build.A warning that can’t be ignored has no form:
CriticalWarningraisesUnhandledCriticalWarningErrorif no collector receives it.
Standoff
Both let execution continue after a warning, and both escalate one to an exception: the filter action
error, or a collector’s handler returningTrue, which raisesEscalatedWarningError.catch_warnings(record=True)collects the warnings of a block in a list, as a collector does.
Advantages
Every library reports through it, the interpreter’s deprecations too, and
-WorPYTHONWARNINGSconfigure it without changing code.The default action shows a warning once per place it is issued from.
logging
Source: logging of Python’s standard library.
Disadvantages
A record goes to the handlers of the logger hierarchy, configured for the application. Returning the warnings of one operation to its caller needs a handler written for it.
Records are selected by their level, not by the class of an exception.
Standoff
logging.captureWarnings()sends the warnings ofwarningsto the loggerpy.warnings.
Advantages
Destinations, formats and levels of the output are configured once for an application.