[Python-Dev] PEP282 and the warnings framework

holger krekel pyth@devel.trillke.net
Wed, 15 May 2002 20:13:42 +0200

Kevin Butler wrote:
> - Programmers tend to avoid creating a new subclass just to log a new message. 

true if you are using java or c++ but not neccesarily for python.
subclassing is done quickly and without error-prone noise. 

But anyway, who says that you should create a new subclass for a new message?

>   This results in lots of inappropriate reuse of the existing message classes, 
> or hesitancy to log a message at all, reducing your ability to configure 
> individual sets of messages you're interested in.  This is similar to the 
> hesitancy to create a new exception subclass, but seems to be stronger - 
> probably because you never 'catch' the logged messages, so the 
> presence/absence of the class doesn't simplify/complicate other code.

Subclassing of exceptions is often not neccessary for simple applications
because python provides a nice hierarchic preset of Exceptions.
For larger applications you *must* define categories of
Errors. Or you decide to pay later :-)

IMO the situation with logging-messages might be very similar.

> In contrast, creating a new Logger (or "Category") instance meets little 
> resistance, and a shift to that model was welcomed by all...except the 
> developer of the message hierarchy logging system.

having a Logger-instance which processes messages is quite orthogonal
to how the messages are categorized. 

> - Some messages are awfully hard to categorize statically:  the severity of a 
> FileNotFound message could be FATAL, WARNING, or DEBUG, depending on what file 
> is not found and the error-handling code around the message,


> so you end up needing multiple FileNotFound message classes.


First of all, you should catch e.g. an IOError close to where it occurs because
the higher up the request-stack the less you know what to do (usually).
The more specific the error the higher up you can catch it (usually)
and still know what to do. 

With 'typed messages' you can achieve the same convenience for the 
logging api e.g. 

    log.debug(x) maps to log.log(DebugMessage(x))
    log.error(x) maps to log.log(ErrorMessage(x))
    log.log(x)   maps to log.log(log.DebugMessage(x))
                 if not isinstance(x,Message)

    (The base Message class should accept Exceptions and Strings IMO.)

> Thus, it is better for the 
> calling code to determine the severity of a message, rather than some static 
> property of the message itself.

With the above definitions you can interprete and dispatch error 
conditions like so:

except IOError,e:
    if e.errno in (a,b,c):
    elif e.errno in (x,y,z):

Where is the advantage if you use integer log levels? 
Am i missing something?

> - Configuring logging by message type is usually less helpful than enabling 
> messages from a specific area of code, so configuring by package or class 
> tends to be more useful.

much like with the warning module there can be more than one parameter
for filtering. This doesn't touch the question how messages
should be categorized (by integer or by class-type).