[Python-Dev] Warning framework
Guido van Rossum
guido@python.org
Sun, 05 Nov 2000 22:35:26 -0500
Before I fall asleep let me write up my ideas about the warning
framework.
Requirements:
- A C-level API that lets C code issue a warning with a single call
taking one or two arguments, e.g. Py_Warning(level, message). (The
'level' argument is an example only; I'm not sure what if any we
need.)
- After the first time a specific warning is issued for a given source
code location, the overhead of calling Py_Warning() should be
minimal.
- An equivalent Python level API, e.g. sys.warning(level, message).
- Flexible control over which warnings are printed or not; there
should be a way to set this up from within the Python program but
also from the command line or possible using an environment
variable.
- Control over the disposition of warnings; by default they should be
printed to sys.stderr but an alternative disposition should be
supported (the mechanism could be either a different file or a
different callback function).
- By default, a warning is printed once (the first time it is issued)
for each source line where it is issued.
- For a specific warning at a specific source code location, it should
be possible to specify the following alternatives:
- Turn it into an exception
- Don't print it at all
- Print it each time it is issued
- It should also be possible to specify these alternatives:
- For all warnings
- For all warnings in a specific module or file
- For all warnings at a specific source code location
- For a specific warning everywhere in a specific module or file
- For a specific warning everywhere in the program
- For all warnings at/above/below (?) a specific level, if we use
warning levels
Possible implementation:
- Each module can has a dictionary __warnings__ in its global
__dict__, which records the state of warnings. It is created as an
emprt dict if it doesn't exist when it is needed. The keys are
(message, linenumber) tuples (the module or file is implicit through
the use of the module's __dict__). The value is None if no more
action is needed for this particular warning and location. Some
other values may indicate the options "always print warning" (1?)
and "raise an exception" (-1?).
- There's a list of "filters" in the sys module
(e.g. sys.warningfilters) that is checked whenever a warning doesn't
have a hit in the __warnings__ dict. Entries in the filter list are
(file, line, message, action) tuples. (If we decide to implement
warning levels, these must also be represented here somewhere.)
- The file must be None or a shell matching pattern, e.g. "*foo";
the ".py" suffix is optional; a partial pathname may be given too.
So "foo/bar" matches "/usr/lib/python2.0/foo/bar.py" but also
"/home/guido/libp/tralala/foo/bar.py". If the file is None or "*"
the filter applies regardless of the file.
- The line must be None or an integer. If the file is None or "*"
(indicating all files) the line must be None and is ignored.
- The message must be a None or a string. If it is None, the filter
applies to all messages. The message string may end in "*" to
match all messages with the given text (up to the "*").
- The action must be one of the following strings:
- "ignore" -- the warning is never printed
- "always" -- the warning is always printed
- "once" -- the warning is printed for the first occurrence
matching the filter
- "module" -- the warning is printed for the first occurrence in
each module matching the filter
- "location" -- the warning is printed for the first occurrence at
each source code location (module + line) matching the filter
- "exception" -- the warning is turned into an exception whenever
it matches the filter
Note: implementation of "once" and "module" require additional
state per filter entry; I'm not sure if that's worth the effort.
- When the warning system decides to print a warning, it is given to
sys.displaywarning(file, line, message), which by default does
something like print >>sys.stderr, file, ":", line, ":", message
- There should be a function sys.addwarningfilter(file, line,
message, action) that appends items to sys.warningfilters after
some sanity checking.
- There should be command line options to specify the most common
filtering actions, which I expect to include at least:
- suppress all warnings
- suppress a particular warning message everywhere
- suppress all warnings in a particular module
- turn all warnings into exceptions
--Guido van Rossum (home page: http://www.python.org/~guido/)