[Python-Dev] PEP282 and the warnings framework
Fri, 17 May 2002 13:24:32 +0100
> They don't have to as long as they don't use custom LogRecord.
Yes, but by offering a class-based interface (user-created LogRecords) I am
more or less encouraging it, since people would not expect adverse effects
just by deriving a class.
> >>def log(event, eventtype=LogRecord):
> >> if not isinstance(event, LogRecord):
> >> event = eventtype(event)
> >> ... the rest of the code
> > I think a better design is to pass in a callable which constructs the
> > LogRecord or a derived class thereof. This way, you can use a class, a
> > function, a bound method which has access to other context, or whatever.
> This will work in my version without a problem, because
> a function is not an instance of LogRecord.
True enough, though it's more by accident than design.
> > def log(..., record=LogRecord):
> > ...check to see if logging will happen...
> > record = record(...args)
> > self.handle(record)
> OK, but when you pass in something that is already a LogRecord instance
> you have a problem with the "record = record(...args)" call. And
The semantics of my suggestion is - pass in a callable which returns an
instance. It wasn't intended to be used for passing in an instance. A class
is just a convenient callable.
> maybe the LogRecord instance would like to decide about whether
> logging should happen or not.
There's already three places where decisions about "whether to process an
event" take place - loggers, handlers and filters. I'm already concerned
about having three, and I'm not sure its a good idea to have a fourth! Some
argument can be made for having the three:
Logger level filtering to control verbosity based on application area -
offers simplicity for best performance
Handler level filtering to control verbosity as shown to a given audience
Filter level filtering to support more flexible filtering, at some cost to
> > The callable would be called with the same arguments as
> > currently is - it can do what it wants with them.
My idea is still incomplete - I still haven't considered what the callable
should be called with (my last suggestion - the same as Logger.makeRecord
is, I think, too clunky).
> But why do you want to move the construction of the LogRecord
> instance into the logger code. Instead of passing the constructor
> arguments of the LogRecord and the type/callable to the logger
> and let the logger create the LogRecord instance, why shouldn't
> it be possible to pass in a LogRecord instance?
I'm not yet sure what's best. The main reason why I wanted to control
LogRecord creation was that some aspects of this creation need to be
thread-safe: particularly the calls which walk the stack to find the
filename/lineno of the caller. But I could make this a method of LogRecord
which is called when the Logger actually starts to process the LogRecord.
The reason I didn't do this initially was that I viewed a LogRecord as just
a home for the event attributes, little more than a dictionary.
> > logger.warn("Hello, %s", "world!", record=myRecordMaker)
> So go one step further and allow:
> logger.warn(myRecordMaker("Hello, %s", "world!"))
It's more than just a step further. In my case, it's an optional argument.
In your case, everyone has to do it that way. I respect your needs, but also
the needs of those who just want to pass a format string and some optional
arguments. After all, most instances of use will probably follow the simpler
> (I assume that MySpecialRecord is derived from LogRecord).
> Either the LogRecord constructor should be responsible
> for creating the timestamp and finding file/line info. etc.
> or this could be done by the logger (via calling a method
> on the LogRecord instance).
Yes, I had the same idea, mentioned earlier in this post. Still thinking on
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com