Random Crashing

45 views
Skip to first unread message

Dustin Hibberd

unread,
Jan 27, 2020, 7:32:48 PM1/27/20
to pyqtgraph
Hello,

I have been using pyqtgraph with pyqt5 on a number of GUI's at my office.  I used to run them all using python 2.7 and didn't have any problems with random crashes.  However, now that I've started using python 3.7, everything seem so much less stable. My GUI's will randomly crash with no traceback / error message. The window simply closes, despite wrapping general try/excepts over most functions that should print out the exception.  I'm using the anaconda package and IPython console built into Spyder. 

The crashing persists
 - on multiple different installs on different computers. 
 - running scripts locally and network based
 - All on python 3.7 and Windows 10
 - sometimes happens when I click buttons
 - sometimes seems to happen due to mouse / hover events

I'm not entirely convinced it's due to the pyqtgraph import but I figured this is a good place to start since my one application that does not use pyqtgraph doesn't seem to have this problem.


I recently got it to be more stable by only running the GUI script once from a specific console instance.   My only lead is that it might has something to do with running the GUI from the console multiple times in a row ( I often do this when I'm adjusting pen colors / layouts etc)

My biggest problem is that I get no traceback or clue as to what's going on. It just closes without any message at all.

Here's a few relevant code snippets: 



import sys
import time
import traceback
import numpy as np
from functools import partial

from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import pyqtSignal
import pyqtgraph.exporters
import pyqtgraph as pg


import DB_Control_v002 as DB
import pyqtGraphPresets_v001 as pgPre

class MainWindow(QtWidgets.QMainWindow):
    
    sigCount = pyqtSignal()
    
    def __init__(self, parent=None):
        super(self.__class__, self).__init__(parent)
                
        # Allows for statistical anylisis from the SPC table
        # if an SPC table is not chosen it is changed to false and no analysis is done
        # if the openened database is closed, it is then turned back to True
        self.statsEnabled = True
        self.statsGraphs = {}
        self.check_list  = []
        
        
        """Create Status Bar"""        
        
        self.MainStatus = self.statusBar()
        
        """ Create MainWindow """
        self.setObjectName("Data Viewer")
        self.resize(1500, 800)
        self.setWindowTitle("Data Viewer")
        
        self.setWindowIcon(QtGui.QIcon('line-chart.png'))
        
        graph_color = pg.mkColor(float(.9))
        pg.setConfigOption('background', graph_color)
        pg.setConfigOption('foreground', 'k')
        
        
        self.layout = QtWidgets.QGridLayout()                #establishes Grid layout style
        self.layout.setContentsMargins(20,20,20,20)
        self.layout.setHorizontalSpacing(9)
        self.layout.setVerticalSpacing(1)
        
        """ Font Creation """
        
        self.font1 = QtGui.QFont("Times New Roman", pointSize=15)
        self.font2 = QtGui.QFont("Helvetica",pointSize=12)
        
        """ Graph Pen Creation """
        self.magenta_line = pg.mkPen(width=1, color='m')
        self.red_line = pg.mkPen(width=1, color='r')
        self.green_line = pg.mkPen(width=1, color=(52, 127, 6), style=QtCore.Qt.DashLine)
        self.yellow_dash = pg.mkPen(width=2, color=(249, 157, 19), style=QtCore.Qt.DashLine)
        self.purp_dash = pg.mkPen(width=1,color=(182, 59, 191), style=QtCore.Qt.DashLine)
        self.blank = QtGui.QColor(0,0,0,0)
        
        """ ToolBar Creation """
        
        toolbar_main = QtWidgets.QToolBar(self)
        toolbar_main.setWindowTitle("Filter")
        toolbar_main.setMovable(False)
        toolbar_main.setIconSize(QtCore.QSize(50,50))
        self.addToolBar(toolbar_main)
        
        self.but_open = QtWidgets.QAction(QtGui.QIcon("download.png"),"Open new SQL Database",self)
        self.but_close = QtWidgets.QAction(QtGui.QIcon("cancel.png"),"Close Database",self)

        self.but_spc = QtWidgets.QAction(QtGui.QIcon("fence.png"),"SPC ",self)
        self.but_spc.setCheckable(True)
        self.but_avg = QtWidgets.QAction(QtGui.QIcon("avg.png"),"Average",self)
        self.but_avg.setCheckable(True)
        self.but_sigma = QtWidgets.QAction(QtGui.QIcon("sigma.png"),"Control Limits",self)
        self.but_sigma.setCheckable(True)
        self.but_minmax = QtWidgets.QAction(QtGui.QIcon("min-max.png"),"Min - Max",self)
        self.but_minmax.setCheckable(True)
        
        self.but_feed = QtWidgets.QAction(QtGui.QIcon("play_grad.png"),"Start live feed.",self)
        self.but_feed.setCheckable(True)
        
        self.stats_but_list = [self.but_spc, self.but_avg, self.but_sigma, self.but_minmax]
        
        spacer_list = [QtGui.QWidget(self) for i in range(3)]
        for spacer in spacer_list:
            spacer.setSizePolicy(QtGui.QSizePolicy.Minimum,QtGui.QSizePolicy.Minimum)
            spacer.setMinimumWidth(40)
        
        toolbar_main.addAction(self.but_open)
        toolbar_main.addAction(self.but_close)
        toolbar_main.addWidget(spacer_list[0])

        toolbar_main.addWidget(spacer_list[1])
        
        toolbar_main.addAction(self.but_spc)
        toolbar_main.addAction(self.but_avg)
        toolbar_main.addAction(self.but_sigma)
        toolbar_main.addAction(self.but_minmax)
        toolbar_main.insertSeparator(self.but_spc)
        
        toolbar_main.addWidget(spacer_list[2])
        
        toolbar_main.addAction(self.but_feed)
        toolbar_main.insertSeparator(self.but_feed)

        """ Create Tab Zone """
       
        self.Tab_zone = QtWidgets.QTabWidget()
        self.Tab_zone.tabCloseRequested.connect(self.closeTab)

        self.layout.addWidget(self.Tab_zone)
        self.setCentralWidget(self.Tab_zone)
        self.setLayout(self.layout)
        
   

        """ Button Connections """
               
        self.but_open.triggered.connect(self.openFile)
        self.but_close.triggered.connect(self.closeFile)
        
        self.but_spc.triggered.connect(self.toggleStatLines)
        self.but_avg.triggered.connect(self.toggleStatLines)
        self.but_sigma.triggered.connect(self.toggleStatLines)
        self.but_minmax.triggered.connect(self.toggleStatLines)
        
        self.but_feed.triggered.connect(self.handleFeed)
        
        
        
        self.updateStatus(0)
        
        
    
    def updateStatus(self, status):
        # 0 = no database opened, or database closed
        # 1 = database opened
        
        if status == 0:
            self.but_open.setEnabled(True)
            self.but_close.setEnabled(False)
            self.but_feed.setEnabled(False)
            
            for but in self.stats_but_list:
                but.setEnabled(False)

        if status == 1:
            self.but_open.setEnabled(False)
            self.but_close.setEnabled(True)
            self.but_feed.setEnabled(True)
            
            for but in self.stats_but_list:
                but.setEnabled(True)


def openSummaryTab(self):
        
        try:
            tab = QtWidgets.QWidget()
            layout = QtWidgets.QGridLayout()
            
            param_list = [col for col in self.dataFrame.columns]

            row_limit = 25
            start_row = 4
            for i, param in enumerate(param_list):
                col = (i)//row_limit
                row = i+start_row - row_limit*col
                button = QtWidgets.QCheckBox(param)
                button.setSizePolicy(QtWidgets.QSizePolicy.Minimum,QtWidgets.QSizePolicy.Expanding)
                button.stateChanged.connect(self.updateSummaryGraph)
                button.stateChanged.connect(partial(self.openStatsTab, button))
                
                self.check_list.append(button)
                layout.addWidget(button,row,col,1,1)
            
            label_Xaxis = QtWidgets.QLabel('Select X-Axis')
            label_Xaxis.setAlignment(QtCore.Qt.AlignCenter)
            label_Xaxis.setSizePolicy(QtWidgets.QSizePolicy.Minimum,QtGui.QSizePolicy.Minimum)
            label_Xaxis.setFont(self.font1)
            
            self.combo_Xaxis = QtWidgets.QComboBox()
            for param in param_list:
                self.combo_Xaxis.addItem(param)
            self.combo_Xaxis.currentIndexChanged.connect(self.sortTableView)
            layout.addWidget(self.combo_Xaxis, 1, 0, 1, layout.columnCount()-1)   
             
            self.text_mode = QtWidgets.QCheckBox('Text Mode')
            layout.addWidget(self.text_mode, 2, 0, 1, layout.columnCount()-1)
            self.text_mode.stateChanged.connect(self.setTextMode)
            
            
            label_Yaxis = QtWidgets.QLabel('Select Y-Axis')
            label_Yaxis.setAlignment(QtCore.Qt.AlignCenter)
            label_Yaxis.setSizePolicy(QtWidgets.QSizePolicy.Minimum,QtGui.QSizePolicy.Minimum)
            label_Yaxis.setFont(self.font1)
            
            layout.addWidget(label_Xaxis,0,0,1,layout.columnCount())
            layout.addWidget(label_Yaxis,3,0,1,layout.columnCount())
   
            self.Xaxis = pgPre.CustomAxis(orientation='bottom')
            if self.text_mode.isChecked():
                self.Xaxis.setTextMode(True)
            
            self.sumGraph = pg.PlotWidget(axisItems={'bottom': self.Xaxis})
            self.sumGraph.showGrid(x=True,y=True)
            self.combo_Xaxis.currentIndexChanged.connect(self.updateSummaryGraph)
            self.combo_Xaxis.currentIndexChanged.connect(self.updateAllStatsGraph)
            self.header.sigUpdate.connect(self.updateSummaryGraph)
            
            self.updateSummaryGraph()
                       
            layout.addWidget(self.sumGraph,0,layout.columnCount(),layout.rowCount(),1)
            
    
    
            tab.setLayout(layout)
            self.Tab_zone.addTab(tab, "Summary")
            
            self.updateStatus(1)

            

        except Exception as ex:
            tb = sys.exc_info()[-1]
            self.MainStatus.showMessage("openSummaryTab Error : {} | Line : {} | Details : {}".format(type(ex).__name__,tb.tb_lineno,ex.args))


    def updateSummaryGraph(self):
            try:
                y_axis_title_list = []
                color_list = ['#0080FF', '#FF0000', '#00FF00','#FF007F',
                              '#00FFFF', '#FF8000',
                              '#7F00FF', '#FF00FF', '#FFFF00',
                              '#E0E0E0', '#606060']             

                self.sumGraph.plot([],[], clear=True)
                
                x_param = self.combo_Xaxis.currentText()
                
                if self.text_mode.isChecked():
                    self.Xaxis.x_list = self.getStrings(x_param)
                    x = list(range(len(self.Xaxis.x_list)))
                
                else:
                    x = self.getGraphData(x_param)
                
                
                    
                color=0
                for item in self.check_list:
                    item.setStyleSheet('')
                    
                    if item.isChecked():
                       
                        y_param = item.text()
                        y = self.getGraphData(y_param)
                        y_axis_title_list.append(y_param)

                        brush = pg.mkBrush(color=color_list[color], symbol='o')
                        self.sumGraph.plot(x, y, pen=color_list[color], symbolBrush=brush, symbolPen='k')
                        
                        
                        item.setStyleSheet("background-color: {}".format(color_list[color]))
                        color += 1
                        if color > (len(color_list)-1):
                            color = 0
            
                self.sumGraph.setLabels(title = 'Summary Graph', left = str(y_axis_title_list), bottom = x_param)



def main():
    try:
        sys.excepthook = traceback.print_exception
        
        app = 0
        app = QtWidgets.QApplication(sys.argv)
        app.setQuitOnLastWindowClosed(True)
        
        
        dlg = MainWindow() 
        dlg.show()
        dlg.raise_()
        
        sys.exit(app.exec_())
        
    except SystemExit as sysEx:
        if sysEx.args[0] == 0:
            pass
        else:
            print(sysEx.args)
        
    except Exception as ex:
       print(ex)
        
if __name__ == "__main__":
    main()

Patrick

unread,
Jan 27, 2020, 9:44:56 PM1/27/20
to pyqtgraph
Hi,

A while back I noticed random crashes on a Windows 7 machine after upgrading PyQt5 to 5.11, which from memory was similar. The same code and Python/PyQt versions on the Linux machines was fine. Didn't spend much time troubleshooting, just did a pip install PyQt5==5.10.1 to downgrade PyQt version and problem went away...

Maybe that will help?

Patrick

Dustin Hibberd

unread,
Jan 28, 2020, 11:57:53 AM1/28/20
to pyqtgraph
Apparently I was on pyqt version 5.9.2.  I updated to 5.9.6 using "conda update pyqt" but I'll have to do some more testing to see if it makes a difference.

Dustin
Reply all
Reply to author
Forward
0 new messages