2

I am trying to use logging's memory handler to buffer log messages to my actual logging handler. You use the memory handler by instantiating it with some arguments, like this:

import logging
buffered_handler = logging.handlers.MemoryHandler(capacity=5,target=myActualHandler)

However, I don't want my application to have to instantiate a handler from logging directly, or pass any of the arguments; I'd like this code to look like this:

import myhandlers
buffered_handler = myhandlers.BufferedRemoteHandler()

The question is: how do I do this? I'd like an attempt to instantiate my BufferedRemoteHandler to actually return logging's MemoryHandler with some specific arguments. I thought of just making BufferedRemoteHandler a function which returns the handler I want; is that the correct way? Is there a way to create a class which, when you instantiate it, actually returns a totally different class?

4 Answers 4

4

Maybe point 3 of PEP 8 is the answer:

Simple is better than complex.

I'd go the function way. Maybe call it something like get_handler() (or get_buffered_remote_handler()) though, so you realize it is something other than a real class at first glance.

Sign up to request clarification or add additional context in comments.

1 Comment

Usually a function of this type is called a Factory Function. In this case you could refer to it as a Handler Factory
3

To answer your exact question, you may, if you like, override __new__() on your subclass to return an instance of a class other than yours.

import logging

class BufferedRemoteHandler(object):
   def __new__(cls):
       return logging.handlers.MemoryHandler(capacity=5,target=myActualHandler)

But I'd actually suggest the function.

4 Comments

thanks for answering the question! this looks pretty elegant; are there any other reasons besides simplicity for recommending the function route?
@Igor, how about the principle of least astonishment?
I'd agree. Returning an instance of some other class is a kind of surprising outcome for a class instantiation operation.
@kindall But isn't that exactly what type() does? It's a class but when instantiated returns the class that was used to instantiate the passed-in object.
1

Yes just make it a function. Something like getMemoryHandler(). THat's the best way to do it. Also, if only one instance of MemoryHandler is going to be around you may want to make it a singleton.

1 Comment

the singleton in this case is already the logging module itself; you set it up once with your handlers and settings, and every subsequent instantiation/import uses those.
0

Well, to answer you directly, yes, there's __new__(). However, I think what would probably be an easier solution would be to either hard code or allow special handler definitions to be registered to myhandlers. You'd define a member method for each handler you want in myhandlers that just instantiated the MemoryHandler as you want and returned it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.