[Python-Dev] PEP282 and the warnings framework

Kevin Butler kbutler@campuspipeline.com
Wed, 15 May 2002 12:32:33 -0600


Fredrik Lundh wrote:
> Kevin Butler wrote:
> 
> 
>>Subclasses should differ in behavior - if they differ only in data, that data 
>>should go into attributes instead. (Yes, this is disputable, but it does tend 
>>to simplify designs.)
> 
> have you ever used exceptions in python?

Yes.

Have you ever noticed how developers tend to re-use an existing exception 
class even when they should define a new subclass?

:-)

Have you ever had to map a 'return code' into an exception hierarchy? Ever 
just wrapped the data value as an attribute instead, pushing the switching 
behavior off to the exception handlers?

Exception subclasses differing only in class name exist because the language 
provides specific support for switching behavior based on the class of a 
caught exception. (Python's string-based exceptions separate that behavioral 
switching from the exception class hierarchy, but their flat namespace is too 
constraining.)

This specific language support pushes the design tradeoff away from the 
simplicity of attributes toward the more complex subclass hierarchy, but often 
not enough to justify a full mapping of all return codes into classes.

In logging, where there is no language support motivation for additional class 
creation, it makes more sense to avoid the subclass creation altogether.

Creating a logger instance with a category value and then sending it lots of 
different types messages is easier than creating multiple Message subclasses 
for different types of messages and sending them to a single logger instance. 
  Since you usually want to turn on all message types in a specific area of 
code anyway, the single category instance works nicely.

Besides, if you want to build a message-based system on top of a 
category-based system, it is easy - mostly just the work you'd have to do 
anyway (not tested, yada-yada):

	class Message:
		logger = Logger( "Message" )
		priority = INFO
		msg = "Message"
		def __init__( self, *args ):
			self.args = args
		def log( self ):
			self.logger.log( self.priority, self.msg, self.args )
		
Usage:

	class MyMessage( Message ):
		logger = Logger( "Message.MyMessage" )
		priority = WARNING
		msg = "MyMessage: Your %s has %s"

	MyMessage( "dog", "fleas" ).log()

kb