【发布时间】:2021-06-06 20:19:23
【问题描述】:
我一直致力于转换一个程序,该程序将 CSV 文件作为建模应用程序的输入,该应用程序迭代了数千个时间步,并对每个时间步进行计算。在这种格式下,程序最多需要 1-2 分钟才能完成。在计算过程中,我使用了一个简单的 TKinter 进度条来指示模拟进度。
使用 PyQT5 完成 UI 后,计算时间显着减慢。现在计算需要 30 多分钟。
我尝试过的事情:
QT 线程:我将计算推送到单独的工作线程,如下所示:https://realpython.com/python-pyqt-qthread/
class Simulator(QObject):
def __init__(self,inputs):
super(Simulator, self).__init__()
self.inputs = inputs
finished = pyqtSignal()
progress = pyqtSignal(int)
def run_task(self):
print(self.inputs)
simEVs(self.inputs)
self.finished.emit()
隐藏 QWidgets 和阻塞信号:对于另一个项目,我发现更新 QTable 小部件会由于发送大量信号而减慢程序速度,因此阻止小部件的信号提高了那里的性能。在这里,我尝试在模拟期间阻止信号并隐藏我的 UI 的所有子元素,但没有效果。
def sleep_ui(self):
children = self.findChildren(QWidget)
for child in children: #ignore the double indent here
child.blockSignals(True)
child.setUpdatesEnabled(False)
child.hide()
def wake_ui(self):
children = self.findChildren(QWidget)
for child in children:
child.blockSignals(True)
child.setUpdatesEnabled(True)
child.show()
在其他代码实现中,我删除了 ui 窗口,并在计算完成后重新创建它,但我试图在此处避免这种情况。
这是我所说的一个例子:
longsim() 使用 UI 需要 0.0029883 秒,不使用 UI 需要 0.0009970 秒,计算时间增加了近 300%。
longsim.py:
import pyqtgraph as pg
import numpy as np
import matplotlib
matplotlib.use('Qt5Agg')
import time
pg.mkQApp()
def longsim():
t = time.time()
# do stuff
tmax = 365*24*4
timev = np.linspace(0,tmax)
for i in timev:
for i in timev: # an example loop with some placeholder calculations
output = i*100
elapsed = time.time() - t
print(elapsed)
stackexchange.py:
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
import os
import matplotlib
from PyQt5 import QtWidgets, QtGui
from longloop import longsim
matplotlib.use('Qt5Agg')
pg.mkQApp()
path = os.path.dirname(os.path.abspath(__file__))
uiFile = os.path.join(path, 'Example.ui')
WindowTemplate, TemplateBaseClass = pg.Qt.loadUiType(uiFile)
class MainWindow(TemplateBaseClass):
def __init__(self):
TemplateBaseClass.__init__(self)
self.setWindowTitle('window')
# Create the main window
self.ui = WindowTemplate()
self.ui.setupUi(self)
self.ui.buttonBox.clicked.connect(self.clicked)
self.show()
def clicked(self):
longsim()
win = MainWindow()
if __name__ == '__main__':
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
这是 UI 文件: 例子.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>640</width>
<height>480</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>10</x>
<y>440</y>
<width>621</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>
【问题讨论】:
-
在我最初的帖子底部添加了示例
-
您为什么希望该代码比 0.0029883 快?如果您正在寻找速度,那么 GUI 不是最佳选择,因为它只能可视化 30Hz 的变化
-
这只是一个示例计算,实际循环大约需要 2-3 分钟才能计算出没有 GUI
-
作为参考,我连续运行了您的示例三遍。我得到了 0.002、0.003 和 0.001。你不能相信这么短的时间循环。只需要改变一个上下文,你的数字就搞砸了。