如何同步Python子进程的输出

时间:2010-07-08 16:44:31

标签: python popen

我认为我在同步运行两个Popen的输出时遇到问题。看起来这两个不同命令行的输出彼此交错。我也尝试使用RLock来防止这种情况发生,但它没有用。

示例输出将是:

cmd1
cmd1
cmd2
cmd2
cmd2
cmd2
cmd1
cmd2

代码如下:

import subprocess
import threading

class PopenWorkerThread(threading.Thread):
    def __init__(self, cmdLine):
        self.lock = threading.RLock()
        self.WebSphereCmdLine = cmdLine
        threading.Thread.__init__(self)

    def run(self):
        logger.error('Runninf: ' + self.WebSphereCmdLine)
        proc = subprocess.Popen(self.WebSphereCmdLine, shell=False, stdout=subprocess.PIPE)
        while True:
            self.lock.acquire()
            print proc.stdout.readline()
            self.lock.release()

def launch():
    commandLine = ['ls -l', 'netstat']
    for cmdLine in commandLine:
        workerThread = PopenWorkerThread(cmdLine)
        workerThread.start()

launch()

有没有办法同步输出,使它们看起来像这样?

cmd1
cmd1
cmd1
cmd1
cmd1
cmd2
cmd2
cmd2
cmd2
cmd2

2 个答案:

答案 0 :(得分:1)

你用一条线的粒度锁定,所以当然来自一个线程的线可以与另一个线的线交替。只要您愿意等到进程结束然后显示其任何输出,您就可以锁定更大的“进程”粒度。当然,你必须为两个线程使用SAME锁 - 让每个线程使用一个完全独立的锁,正如你现在所做的那样,显然无法实现任何目标。

所以,例如:

导入子流程 导入线程

class PopenWorkerThread(threading.Thread):

lock = threading.RLock()  # per-class, NOT per-instance!

def __init__(self, cmdLine):
    self.WebSphereCmdLine = cmdLine
    threading.Thread.__init__(self)

def run(self):
    logger.error('Runninf: ' + self.WebSphereCmdLine)
    proc = subprocess.Popen(self.WebSphereCmdLine, shell=False, stdout=subprocess.PIPE)
    result, _ = proc.communicate()
    with self.lock:
        print result,

def launch():     commandLine = ['ls -l','netstat']     对于commandLine中的cmdLine:         workerThread = PopenWorkerThread(cmdLine)         workerThread.start()

发射()

答案 1 :(得分:0)