The acid test is to see if you can avoid terms like "Writer", "Printer", and whether someone is able to explore your API using the REPL.
>>> import log
>>> log.log(log.CRITICAL, 'PrintModule', 'Printer failure', sys.exc_info())
PrintModule: Printer failure
>>> print log.configuration
[<function printToStdErr as 0xcafebad>]
>>> log.configuration.clear()
>>> print log.configuration
[]
>>> def send_mail(level, module, message, exception):
... import smtplib
... smptlib.SMTP('mail.test.com').send('syslog@test.com',
... 'no-reply@mysystem.com', module + ' ' + message)
...
>>> log.configuration.append(send_mail)
>>> log.log(log.CRITICAL, 'PrintModule', 'Printer failure', sys.exc_info())
etc.
Next, configuration must be straightforward. >>> import log
>>> log.configuration.extend([
... log.sendmail,
... log.syslog,
... log.rotatinglog])
...
>>> log.sendmail.to = 'admin@test.com'
Notice how this can easily be captured into a file you might name as logconfig.pyYou might be wondering how to assign an attribute to a function, like sendmail.to?
In this particular case, sendmail is actually a class that masquerades as a function.
>>> class Sendmail:
... to = None
...
... def __call__(self, level, module, msg, exc):
... # et. c
...
>>> sendmail = Sendmail()
This way, the most common use-case, i.e. to be notified when something happens is easy to apply, while more complicated ones are only a short step away.