似乎很危险地无法将由子处理程序的Pool()启动的所有子进程链接到PyQt Progress Bar小部件。这是示例代码。显然,没有什么事情阻止我梦想成真。

这个概念:

externalFunc()执行所有主要任务。通过将其VALUE存储到用以下方法声明的poolDict变量中,它不时将其“进度值”发送到MainWindow()实例:

poolDict=manager.dict()


同时,myEvenListener()方法在后台运行,等待VALUE被“发布”。一旦“接收到VALUE”,myEvenListener()就会将ProgressBar更新为接收到的VALUE,并将其重置为零(以避免重复的progressBar更新)。
在尝试更新ProgressBar之前,myEvenListener(self)会通过使用以下步骤来验证ProgressBar尚未达到其最大值100:

if pb.value()>=100: continue


不幸的是,即使externalFunc()提供了足够多的值(160),ProgressBar也从未达到100。除此之外,无法在while循环中退出MainWindow()。

阅读此代码之前,请小心运行,因为它可能会在您的计算机上生成多个python进程,这些进程必须终止。

题:


为什么ProgressBar从未达到最大值100
如何确保不需要时myEvenListener()方法未运行。
如何确保所有子流程在以下时间后消失:
一种。所有的progressBars都是100%
b。用户关闭对话框或终止主进程。




import sys, time
from PyQt4 import QtCore, QtGui

import multiprocessing as mp
from multiprocessing import Pool
manager = mp.Manager()

poolDict=manager.dict()

class PbWidget(QtGui.QProgressBar):
    def __init__(self, parent=None, total=20):
        super(PbWidget, self).__init__()
        self.setMinimum(1)
        self.setMaximum(total)
        self._active = False

    def update_bar(self, to_add_number):
        while True:
            time.sleep(0.01)
            value = self.value() + to_add_number
            self.setValue(value)
            QtGui.qApp.processEvents()
            if (not self._active or value >= self.maximum()):
                break
        self._active = False

    def closeEvent(self, event):
        self._active = False


def externalFunc(each):
    for i in range(16):
        print i
        poolDict[each]=10+i
        time.sleep(0.5)


class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        # self.myList=[.1, .3, .5, 1.0, 1.5, 2.9, 3.1]
        self.myList=[1]
        self.main_layout = QtGui.QVBoxLayout()
        self.pBars={}
        self.state=True

        for each in self.myList:
            pb=PbWidget(total=101)
            self.main_layout.addWidget(pb)
            self.pBars[each]={'pb':pb, 'value':0, 'total_value':0}

        ok_button = QtGui.QPushButton("OK")
        ok_button.clicked.connect(self.OK)
        self.main_layout.addWidget(ok_button)

        central_widget = QtGui.QWidget()
        central_widget.setLayout(self.main_layout)
        self.setCentralWidget(central_widget)

    def myEvenListener(self):
        """This function runs at the background as an infinite while loop. It constantly reads
        a value stored in poolDict variable to which externalFunc() writes a new value every second.
        The value represents a 'Progress' and needs to be passes to Progress Bar widget to which only MainWindow()
        class has an access. After a Value was read it is used to update a Progress Bar.
        After a progress bar was updated the Value is reset to zero.
        The Problem: 'if pb.value()>=100' statement is used to make sure the function doesn't loop if the ProgressBar
        is already reached 100. By some reason the bar never reaches its maximum 100 even while externalFunc() calls
        enough times to reach this number. An ussue # 2: There is no meachanism to exit this while loop without adding
        three more variables... Can it be achieved with what we already have?
        """
        while self.state:
            for each in self.pBars:
                pb = self.pBars[each]['pb']
                print "\n Current Bar value =", pb.value()
                if pb.value()>=100:
                    print 'skipping'
                    continue

                value=None
                if each in poolDict.keys():
                    # read delivered value
                    delivered_value=poolDict[each]
                    # reset delivered value
                    poolDict[each]=0
                    # update bar with delivered value
                    if ( 101-pb.value() ) < delivered_value:
                        print "\n\t UPDATING WITH "
                        pb.update_bar( 101-pb.value() )
                        print "\n\t AFTER ", pb.value()
                    else:
                        pb.update_bar( delivered_value )
                    # print '\n\t\t\t  Updating bar using this value', delivered_value


    def OK(self):
        pool = Pool(processes=3)
        pool.map_async( externalFunc, self.myList)
        self.myEvenListener()

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = MainWindow()
    window.resize(480, 320)
    window.show()
    sys.exit(app.exec_())

最佳答案

这是修改后的代码。它似乎运行良好并且非常稳定。

import sys, time
from PyQt4 import QtCore, QtGui

import multiprocessing as mp
from multiprocessing import Pool
manager = mp.Manager()
poolDict=manager.dict()

class PbWidget(QtGui.QProgressBar):
    def __init__(self, parent=None, total=20):
        super(PbWidget, self).__init__()
        self.setMinimum(1)
        self.setMaximum(total)
        self._active = False

    def update_bar(self, to_add_number):
        while True:
            time.sleep(0.01)
            value = self.value() + to_add_number
            self.setValue(value)
            QtGui.qApp.processEvents()
            if (not self._active or value >= self.maximum()):
                break
        self._active = False

    def closeEvent(self, event):
        self._active = False


def externalFunc(each):
    for i in range(16):
        value =10+i
        poolDict[each]=value
        time.sleep(each)


class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.myList=[.5, .8, 1.2, 1.8, 2.2, .3, .1]

        self.main_layout = QtGui.QVBoxLayout()
        self.pBars={}
        self.state=True
        self.name=None

        for each in self.myList:
            pb=PbWidget(total=101)
            self.main_layout.addWidget(pb)
            self.pBars[each]={'pb':pb, 'name':each}

        ok_button = QtGui.QPushButton("Distribute")
        ok_button.clicked.connect(self.OK)
        self.main_layout.addWidget(ok_button)

        central_widget = QtGui.QWidget()
        central_widget.setLayout(self.main_layout)
        self.setCentralWidget(central_widget)

    def myEvenListener(self):
        """This function runs at the background as an infinite loop. It is constantly reading
        a value stored in poolDict variable to which externalFunc() writes a new value.
        The value represents a 'Progress' and needs to be passed to Progress Bar widget to which MainWindow()
        class has an access. After a Value was read and used to update a Progress Bar it is reset to zero.
        """
        entities = self.pBars.keys()
        while self.state:
            for each in entities:
                if each not in self.pBars.keys():   continue

                pb = self.pBars[each]['pb']
                if pb.value()>=100:
                    self.pBars.pop(each, None)

                value=None
                if each in poolDict.keys():
                    # read delivered value
                    delivered_value=poolDict[each]
                    # reset delivered value
                    poolDict[each]=0
                    # update bar with delivered value
                    if ( 101-pb.value() ) < delivered_value:
                        pb.update_bar( 101-pb.value() )
                    elif delivered_value>0:
                        pb.update_bar( delivered_value )

                if len(self.pBars.keys())==0:
                    self.state=False

    def OK(self):
        pool = Pool(processes=3)
        pool.map_async( externalFunc, self.myList)
        self.myEvenListener()

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = MainWindow()
    window.resize(480, 320)
    window.show()
    sys.exit(app.exec_())

关于python - Python:如何将多进程链接到多进度条,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22336722/

10-13 01:19