gpt4 book ai didi

Python:如何将多进程链接到多进度条

转载 作者:行者123 更新时间:2023-12-01 05:21:11 26 4
gpt4 key购买 nike

看来我已经非常接近能够将子处理的 Pool() 启动的所有子进程链接到 PyQt 进度条小部件了。这是示例代码。显然没有什么流程可以阻止我的梦想发生。

概念:

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

poolDict=manager.dict()

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

if pb.value()>=100: continue

不幸的是,即使 externalFunc() 提供了足够多的值 (160),ProgressBar 也永远不会达到 100。除此之外,没有办法退出 MainWindow() while 循环。

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

问题:

  1. 为什么 ProgressBar 永远不会达到最大值 100
  2. 如何确保 myEvenListener() 方法在不需要时不运行。
  3. 如何确保所有子进程在以下情况后终止:A。所有进度条都处于 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_())

最佳答案

enter image description here

这是修改后的代码。看起来运行良好并且相当稳定。

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:如何将多进程链接到多进度条,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22336722/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com