如何同步Python子进程的输出

发布于 2024-09-08 20:28:02 字数 1017 浏览 3 评论 0原文

我认为我在同步同时运行的两个 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

I think I'm having issues to synchronize the output of two Popen running concurrently. It seems that the output from these two different command lines are interleaved with one another. I also tried using RLock to prevent this from happening but it didn't work.

A sample output would be:

cmd1
cmd1
cmd2
cmd2
cmd2
cmd2
cmd1
cmd2

The code is as attached:

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()

Is there a way to synchronize the outputs so that they look like such?

cmd1
cmd1
cmd1
cmd1
cmd1
cmd2
cmd2
cmd2
cmd2
cmd2

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

孤者何惧 2024-09-15 20:28:02

您以行的粒度进行锁定,因此一个线程中的行当然可以并且确实与另一个线程中的行交替。只要您愿意等到进程结束后再显示其任何输出,您就可以使用更大的“进程”粒度进行锁定。当然,您必须对两个线程使用相同的锁——让每个线程使用完全独立的锁,就像您现在所做的那样,显然根本无法实现任何目标。

因此,例如:

import subprocess
import threading

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']
    for cmdLine in commandLine:
        workerThread = PopenWorkerThread(cmdLine)
        workerThread.start()

launch()

You're locking with a granularity of a line, so of course lines from one thread can and do alternate with lines from the other. As long as you're willing to wait until a process ends before showing any of its output, you can lock with the larger "process" granularity. Of course you have to use the SAME lock for both threads -- having each thread use a completely separate lock, as you're doing now, cannot achieve anything at all, obviously.

So, for example:

import subprocess
import threading

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']
    for cmdLine in commandLine:
        workerThread = PopenWorkerThread(cmdLine)
        workerThread.start()

launch()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文