简体   繁体   English

结合 PYQT GUI 显着增加了循环时间

[英]Incorporating PYQT GUI significantly increases loop time

I have been working on converting a program which took a CSV file as inputs for a modelling application that iterated over several thousant timesteps and and did calculations on each.我一直致力于转换一个程序,该程序将 CSV 文件作为建模应用程序的输入,该应用程序迭代了数千个时间步,并对每个时间步进行计算。 In this format, the program took 1-2min max to complete.在这种格式下,程序最多需要 1-2 分钟才能完成。 During the calculation I utilized a simple TKinter progress bar to indicate simulation progress.在计算过程中,我使用了一个简单的 TKinter 进度条来指示模拟进度。

With the completed UI using PyQT5, the calculation time slows down significantly.使用 PyQT5 完成 UI 后,计算时间显着减慢。 It now takes 30+ minutes to calculate.现在计算需要 30 多分钟。

Things I have tried:我尝试过的事情:

QT threading: I pushed the calculation to a separate worker thread as outline here: https://realpython.com/python-pyqt-qthread/ 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()

Hiding QWidgets & Blocking signals: for another project I found that updating a QTable widget, slowed down the program due to a multitude of signals being sent, so blocking signals for the widget increased performance there.隐藏 QWidgets 和阻塞信号:对于另一个项目,我发现更新 QTable 小部件会由于发送大量信号而减慢程序速度,因此阻止小部件的信号提高了那里的性能。 Here I tried blocking signals and hiding all child elements of my UI during the simulation to no effect.在这里,我尝试在模拟期间阻止信号并隐藏我的 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()

In other code implementations, I've deleted the ui window and recreated it once the calculation has completed, but I'm trying to avoid that here.在其他代码实现中,我删除了 ui window 并在计算完成后重新创建它,但我试图在这里避免这种情况。

here is an example of what I am talking about:这是我正在谈论的一个例子:

longsim() takes 0.0029883 secs with the UI and 0.0009970 secs without, an almost 300% increase in computation time. longsim() 使用 UI 需要 0.0029883 秒,不使用 UI 需要 0.0009970 秒,计算时间增加了近 300%。

longsim.py: 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:堆栈交换.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_()

here is the UI file: example.ui这是 UI 文件:example.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>

Thank you all for the suggestions, As is usually the case for things like this the bug was elsewhere.谢谢大家的建议,通常情况下,像这样的错误在其他地方。 After fixing a value that should have been a percentage (0-1 instead of 0-100) the loop runs as it should.在修复了一个应该是百分比的值(0-1 而不是 0-100)之后,循环将按应有的方式运行。 no issues with increased loop times as of yet.到目前为止,还没有增加循环时间的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM