[Python-Dev] Re: PEP 282 comments

Kevin Butler kbutler@campuspipeline.com
Thu, 21 Mar 2002 16:52:19 -0700


[Guido van Rossum wrote]

> I'd like to call YAGNI on this.  Also on the idea of being able
> to pass an exception to all logging levels.  

I'd like to "Not Need It" as well, but the code I've written
using log4j and the code I've written & maintained with a couple of other
logging systems have needed it.

The problem is that without easy "log exception at specific level",
the natural way to write code is:

try:
  something()
except Failure:
  log.exception( "couldn't do something" )
  # proceed with defaults

That log statement is useful in debugging or maybe as a warning,
but is definitely not an ERROR, because the computer has a
valid way to continue the operation.

[Guido]
> Also on the idea of passing the exc_info in rather than 
> having the logger call sys.exc_info().

The implicit sys.exc_info() is definitely the more common case.
However, I often try something else in case of a failure, but 
if that retry fails, I want to log the original failure, not 
subsequent failures in the retry.

try:
  something()
except SomethingBroke:
  failure = sys.exc_info() # could log here, but only as debug
  try:
     recover()
  except RecoveryFailed:
     log.error( 
        "Something broke and I couldn't recover", 
        exc=failure  # not sys.exc_info()
        )

[Jeremy Hilton wrote:]
> The feature is simple to explain and implement, and seems to have low
> implementation cost.  So I certainly think it meets the simplest thing
> that could possibly work criteria.

+1

And it promotes "there's one obvious way to do it".
And it is consistent with existing de facto standard systems.

[Jeremy]
> Why do you need **kwargs at all?  

So we can postpone formatting the optional arguments into a message
until after we test if we're going to log the message or not.

[Jeremy]
> Can't the interface specify the
> complete set of optional arguments explicitly?

Explicitly-specified keyword arguments are awkward
with *args.

class Log:
  def info1( self, msg, exc=None, *args ):
    ...
  def info2( self, msg, *args, **kwargs ):
    ...


log.info1( "When %s %s", None, "pigs", "fly" )
log.info1( "When %s %s", failure, "pigs", "fly" )

log.info2( "When %s %s", "pigs", "fly" )
log.info2( "When %s %s", "pigs", "fly", exc=failure )

kb