tags:

views:

198

answers:

1

I have the following code:

#!/usr/bin/env python
import logging
import sys
import copy

class Wrapper:
    def write(self, s):
        #sys.__stdout__.write(s)
        loggy = logging.getLogger('foobar')
        loggy.info(s)

def blah():
    logger = logging.getLogger('foobar')
    logger.setLevel(logging.DEBUG)
    streamhandle = logging.StreamHandler(sys.stdout)
    streamhandle.setFormatter(logging.Formatter('[%(message)s]'))
    logger.addHandler(streamhandle)

    sys.stdout = Wrapper()
    sys.stderr = Wrapper()

if __name__ == '__main__':

    blah()
    logger = logging.getLogger('')
    #print logger.handlers
    #for handler in logger.handlers:
    #    print handler

    fooy = logging.getLogger('foobar')
    #print fooy.handlers

    sys.stdout.write('i love you')

    logging.log(logging.DEBUG, 'i love you')

This code causes python to go in an infinite recursive loop, and the output is actually incredibly cool:

[Error in sys.exitfunc:
]
[INFO:foobar:Error in sys.exitfunc:

]
[INFO:foobar:INFO:foobar:Error in sys.exitfunc:


]
[INFO:foobar:INFO:foobar:INFO:foobar:Error in sys.exitfunc:



]
[INFO:foobar:INFO:foobar:INFO:foobar:INFO:foobar:Error in sys.exitfunc:




]
[INFO:foobar:INFO:foobar:INFO:foobar:INFO:foobar:INFO:foobar:Error in sys.exitfunc:

This keeps growing exponentially :) Its pretty but why is this happening?

+5  A: 

The infinite loop is happening because your logger's StreamHandler is set to write its log messages to sys.stdout, but sys.stdout is in turn wrapped and writes back to the very logger that just sent it a write message.

Depending on your goals, you're probably better having the Wrapper actually perform output, rather than use logging internally. Something like:

class Wrapper(object):
    def write(self, s):
        sys.__stdout__.write(s) # sys.__stdout__ points to the original stdout, rather
                                # than the redirected sys.stdout
Jarret Hardie
If i change this to: streamhandle = logging.StreamHandler(sys.__stdout__) so it now points to the orignal sys.stdout. This doesnt fix the issue but why?
UberJumper
Sorry, do you mean "this does fix the issue, but why?" or "this does not fix the issue... why?"
Jarret Hardie
It doesn't fix the issue. Since this streamhandler is pointing to the orignal sys.stdout, why should this be calling the wrapper?
UberJumper
Not sure... I entered the code you have above, and substituted StreamHandler(sys.__stdout__), and it's working quite nicely.
Jarret Hardie