View difference between Paste ID: nbwErU5a and NWywMuNP
SHOW: | | - or go back to the newest paste.
1
#!/usr/bin/python
2
#
3
# Runner with stdout/stderr catcher
4
#
5
from sys import argv
6
from subprocess import Popen, PIPE
7
import os, io
8
from threading import Thread
9
import Queue
10
def __main__():
11
    if (len(argv) > 1) and (argv[-1] == "-sub-"):
12
        import time, sys
13
        print "Application runned!"
14
        time.sleep(2)
15
        print "Slept 2 second"
16
        time.sleep(1)
17
        print "Slept 1 additional second",
18
        time.sleep(2)
19
        sys.stderr.write("Stderr output after 5 seconds")
20
        print "Eol on stdin"
21
        sys.stderr.write("Eol on stderr\n")
22
        time.sleep(1)
23
        print "Wow, we have end of work!",
24
    else:
25
        os.environ["PYTHONUNBUFFERED"]="1"
26
        try:
27
            p = Popen( argv + ["-sub-"],
28
                       bufsize=0, # line-buffered
29
                       stdin=PIPE, stdout=PIPE, stderr=PIPE )
30
        except WindowsError, W:
31
            if W.winerror==193:
32
                p = Popen( argv + ["-sub-"],
33
                           shell=True, # Try to run via shell
34
                           bufsize=0, # line-buffered
35
                           stdin=PIPE, stdout=PIPE, stderr=PIPE )
36
            else:
37
                raise
38
        inp = Queue.Queue()
39
        sout = io.open(p.stdout.fileno(), 'rb', closefd=False)
40
        serr = io.open(p.stderr.fileno(), 'rb', closefd=False)
41-
        def rOut():
41+
        def Pump(stream, category):
42-
            while True:
42+
            queue = Queue.Queue()
43-
                part_line = sout.peek(io.DEFAULT_BUFFER_SIZE)
43+
            def rdr():
44-
                if len(part_line)>0:
44+
                while True:
45-
                    inp.put( ('stdout', sout.read(len(part_line)) ) )
45+
                    buf = stream.read1(8192)
46-
                else:
46+
                    if len(buf)>0:
47-
                    return
47+
                        queue.put( buf )
48-
        def rErr():
48+
                    else:
49-
            while True:
49+
                        queue.put( None )
50-
                part_line = serr.peek(io.DEFAULT_BUFFER_SIZE)
50+
                        return
51-
                if len(part_line)>0:
51+
            def clct():
52-
                    inp.put( ('stderr', serr.read(len(part_line)) ) )
52+
                active = True
53-
                else:
53+
                while active:
54-
                    return
54+
                    r = queue.get()
55-
        thOut = Thread(target=rOut)
55+
                    try:
56-
        thOut.setDaemon(True)
56+
                        while True:
57-
        thOut.start()
57+
                            r1 = queue.get(timeout=0.005)
58-
        thErr = Thread(target=rErr)
58+
                            if r1 is None:
59-
        thErr.setDaemon(True)
59+
                                active = False
60-
        thErr.start()
60+
                                break
61
                            else:
62
                                r += r1
63
                    except Queue.Empty:
64
                        pass
65
                    inp.put( (category, r) )
66
            for tgt in [rdr, clct]:
67
                th = Thread(target=tgt)
68
                th.setDaemon(True)
69
                th.start()
70
        Pump(sout, 'stdout')
71
        Pump(serr, 'stderr')
72
73
        while p.poll() is None:
74
            # App still working
75
            try:
76
                chan,line = inp.get(timeout = 1.0)
77
                if chan=='stdout':
78
                    print "STDOUT>>", line, "<?<"
79
                elif chan=='stderr':
80
                    print " ERROR==", line, "=?="
81
            except Queue.Empty:
82
                pass
83
        print "Finish"
84
85
if __name__ == '__main__':
86
    __main__()