Constantly print Subprocess output while process is running

后端 未结 13 802
庸人自扰
庸人自扰 2020-11-22 06:51

To launch programs from my Python-scripts, I\'m using the following method:

def execute(command):
    process = subprocess.Popen(command, shell=True, stdout=s         


        
13条回答
  •  清酒与你
    2020-11-22 07:49

    In case someone wants to read from both stdout and stderr at the same time using threads, this is what I came up with:

    import threading
    import subprocess
    import Queue
    
    class AsyncLineReader(threading.Thread):
        def __init__(self, fd, outputQueue):
            threading.Thread.__init__(self)
    
            assert isinstance(outputQueue, Queue.Queue)
            assert callable(fd.readline)
    
            self.fd = fd
            self.outputQueue = outputQueue
    
        def run(self):
            map(self.outputQueue.put, iter(self.fd.readline, ''))
    
        def eof(self):
            return not self.is_alive() and self.outputQueue.empty()
    
        @classmethod
        def getForFd(cls, fd, start=True):
            queue = Queue.Queue()
            reader = cls(fd, queue)
    
            if start:
                reader.start()
    
            return reader, queue
    
    
    process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    (stdoutReader, stdoutQueue) = AsyncLineReader.getForFd(process.stdout)
    (stderrReader, stderrQueue) = AsyncLineReader.getForFd(process.stderr)
    
    # Keep checking queues until there is no more output.
    while not stdoutReader.eof() or not stderrReader.eof():
       # Process all available lines from the stdout Queue.
       while not stdoutQueue.empty():
           line = stdoutQueue.get()
           print 'Received stdout: ' + repr(line)
    
           # Do stuff with stdout line.
    
       # Process all available lines from the stderr Queue.
       while not stderrQueue.empty():
           line = stderrQueue.get()
           print 'Received stderr: ' + repr(line)
    
           # Do stuff with stderr line.
    
       # Sleep for a short time to avoid excessive CPU use while waiting for data.
       sleep(0.05)
    
    print "Waiting for async readers to finish..."
    stdoutReader.join()
    stderrReader.join()
    
    # Close subprocess' file descriptors.
    process.stdout.close()
    process.stderr.close()
    
    print "Waiting for process to exit..."
    returnCode = process.wait()
    
    if returnCode != 0:
       raise subprocess.CalledProcessError(returnCode, command)
    

    I just wanted to share this, as I ended up on this question trying to do something similar, but none of the answers solved my problem. Hopefully it helps someone!

    Note that in my use case, an external process kills the process that we Popen().

提交回复
热议问题