catch output of threads

William wilk-spamout at flibuste.net
Sat Nov 30 05:57:05 EST 2002


Erik Max Francis <max at alcyone.com> writes:

> William wrote:
> 
> > Is it possible to catch the output from print of differents threads ?
> > In a single thread, i can change the value of sys.stdout... but with
> > differents thread i don't know ?
> > 
> > My goal is to make a little server with multithread working on
> > windows without calling an external interpreter (like CGIHTTPServer
> > do).
> 
> For my templating system EmPy -- which is not threaded -- I was forced
> to put together a system where a sys.stdout is replaced with a proxy
> object that can be "pushed and popped" by each evaluation/execution that
> might conceivably use sys.stdout or a print statement, so that the proxy
> object would direct the output to the output stream of the appropriate
> interpreter that was running.
> 
> Unfortunately, though, this doesn't lend itself to a multithreaded
> environment (and is the primary reason why EmPy does not support
> threading), since you could easily encounter deadlocks (if, say, one
> thread stays in an execution loop for an indefinite period).  I don't
> think there's any way to do what you want short of modifying the Python
> interpreter.

I did something who seems to work, thanks to Jeff Epler.
Say me what you think about that :

The OutputThread record output in a dictionary with the ident of thread
as key.
In the end of thread i send the output to the good socket

class OutputThread:
    def __init__(self):
        self.pidout = {}
        self.current_thread = thread.get_ident()
        
    def write(self, ch):
        thread_id = thread.get_ident()

        if thread_id == self.current_thread:
            sys.__stdout__.write(str(ch).upper())
            
        if not self.pidout.has_key(thread_id):
            self.pidout[thread_id] = cStringIO.StringIO()
        self.pidout[thread_id].write(ch)

    
    def envoi(self, stdout):
        thread_id = thread.get_ident()
        if self.pidout.has_key(thread_id):
            stdout.write(self.pidout[thread_id].getvalue())
            del self.pidout[thread_id]
            stdout.flush()
            stdout.close()
            

class Tache(threading.Thread):
    def __init__(self, stdin, stdout, environ, to_run):
        threading.Thread.__init__(self)
        self.stdout = stdout
        self.stdin = stdin
        self.to_run = to_run
        self.environ = environ

    def run(self):
        self.to_run.run(stdout = self.stdout, stdin = self.stdin, environ = self.environ)
        sys.stdout.envoi(self.stdout)

...CGIHTTPServer who run a Tache
sys.stdout = OutputThread()
...run server_forever...

-- 
William Dode - http://flibuste.net



More information about the Python-list mailing list