Python Forum

Full Version: A single Thread Crashes
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
I create a wxPython Window app with a 1-second timer displaying clock on status bar, and a 5-minute timer running a function called Update1 every 5 minutes to download data and update a wx.Grid. I also add time.sleep in different places as need.
When using a single Thread to run Update1 every 5 minutes, it crashes during update, saying 'Not responding..'.
Will timer or sleep cause the crash? any solution? Thanks.
In order to answer this question properly, we will need to see the code that crashed, along with the full error traceback.
I doubt that it was caused by the time or sleep routine.
(Aug-24-2017, 10:09 PM)ian Wrote: [ -> ]I also add time.sleep in different places as need.
Using time.sleep() will block the main loop of GUI.
use a wx.Timer() it run in own event loop that is non-blocking. 
Timer demo blog,and doc.
Didn't know that. I use wx.Timer in https://python-forum.io/Thread-wxpython-...ecognition
I spent 2 days to try on Windows 7 / 10 and x64 / x32; cut the code to minimum and remove all calls to timer & sleep but still crash with stop message (Not Responding) "Python has stopped working. A problem caused the program to stop working correctly. Windows will close the program and notify you if a solution is available." when not calling the thread, it seems ok. since the function code is kind of long. Let me know if need, I will post. I use python 3.6.2. Thanks.
import wx
import wx.grid
import pandas as pd
import googlefinance.client as gf
from threading import *

class RunThread(Thread):
    def __init__(self, event, win):
        Thread.__init__(self)
        self.stopped = event
        self.start()
    def run(self):
        print('Loading 0,0 ..')
        #win.Update_5M(0, 0)
        while True:
            print('Loading 1,12 ..')
            #win.Update_5M(1, 12)
            self.stopped.wait(20)
class Frame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="Thread Crash", size=(530, 742), pos = (500, 100))
        wx.Panel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(sizer)
        self.grid = self.Create_Grid()
        stopFlag = Event()
        RunThread(stopFlag, self)
    def Update_5M(self, n, m):
        self.dfg, self.dfr = self.Load_Data_Frame(n)
        self.Update_Grid(self.dfr, self.grid, 'red', m)
        self.Update_Grid(self.dfg, self.grid, 'green', m)
    def Create_Grid(self):
        self.colno = 11
        self.colsz = [43,40,22,40,44,60,40,40,40,40,40]
        grid = wx.grid.Grid(self, size=(522, 700), pos=(0,0))
        grid.CreateGrid(1,11)
        grid.SetRowLabelSize(60)
        grid.SetLabelFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
        grid.SetDefaultCellAlignment(wx.ALIGN_RIGHT,wx.ALIGN_CENTRE)
        for col in range(self.colno):
            grid.SetColSize(col,self.colsz[col])
        return grid
if __name__ == "__main__":
    app = wx.App()
    win = Frame()
    win.Show()
    app.MainLoop()
It seems to be working to a point for me.
I run windows 7 pro
python 3.6.2
wxpython phoenix 4.0.0b1
[attachment=231]

output:
Output:
starting Frame Starting thread Loading 0,0 .. Loading 1,12 .. Loading 1,12 ..
I added the print statements.

Phoenix version??
Yes, It works for me too because I commented out the functions (win.Update_5M) that crash. I added the functions back as below. Please let me know if it crashes or not on your machine. I use python 3.6.2 64bit with wxPython-4.0.0a3-cp36-cp36m-win_amd64.whl. win.Update_5M will run 1+ minutes before loading data in the grid.
import wx
import wx.grid
import pandas as pd
import googlefinance.client as gf
from threading import *

class RunThread(Thread):
    def __init__(self, event, win):
        Thread.__init__(self)
        self.stopped = event
        self.start()
    def run(self):
        print('Loading 0,0 ..')
        win.Update_5M(0, 0)
        while True:
            print('Loading 1,12 ..')
            win.Update_5M(1, 12)
            self.stopped.wait(20)
class Frame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="Thread Crash", size=(530, 742), pos = (500, 100))
        wx.Panel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(sizer)
        self.grid = self.Create_Grid()
        stopFlag = Event()
        RunThread(stopFlag, self)
    def Update_5M(self, n, m):
        self.dfg, self.dfr = self.Load_Data_Frame(n)
        self.Update_Grid(self.dfr, self.grid, 'red', m)
        self.Update_Grid(self.dfg, self.grid, 'green', m)
    def Create_Grid(self):
        self.colno = 11
        self.colsz = [43,40,22,40,44,60,40,40,40,40,40]
        grid = wx.grid.Grid(self, size=(522, 700), pos=(0,0))
        grid.CreateGrid(1,11)
        grid.SetRowLabelSize(60)
        grid.SetLabelFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
        grid.SetDefaultCellAlignment(wx.ALIGN_RIGHT,wx.ALIGN_CENTRE)
        for col in range(self.colno):
            grid.SetColSize(col,self.colsz[col])
        return grid
    def Update_Grid(self, df_head, grid, gor, n):
        cols = grid.GetNumberCols()
        rows = grid.GetNumberRows()
        rl = []
        for r in range(rows): rl.append(grid.GetRowLabelValue(r+n))
        for row in range(len(df_head.index)):
            r = row + n
            grid.InsertRows(r,1,False)
            param = {'q': df_head.values[row, 0],'i': "86400",'x': "TSE",'p': "5d"}
            df = gf.get_price_data(param).tail(1)
            o = 0
            if len(df) < 1:
                grid.DeleteRows(r,1,False)
                r -= 1
                o += 1
                continue
            PP = (df.values[0,1] + df.values[0,2] + df.values[0,3]) / 3
            for col in range(self.colno):
                if col != 2:
                    if n == 0:
                        if gor == 'green': grid.SetCellBackgroundColour(r, col, wx.Colour(row*50,200,row*40))
                        if gor == 'red': grid.SetCellBackgroundColour(r, col, wx.Colour(200,row*50,row*40))
                    else:
                        if gor == 'green': grid.SetCellBackgroundColour(r, col, wx.Colour(row*50,255,row*40))
                        if gor == 'red': grid.SetCellBackgroundColour(r, col, wx.Colour(255,row*50,row*40))
                if col == 2:   d = ('%.0f' %df_head.values[row, col])
                elif col == 0: d = df_head.values[row, col]
                elif col == 5: d = format(df_head.values[row, col], "8,d")
                elif col < 6: d = ('%.2f' %df_head.values[row, col])
                elif col == 6: d = '%.2f' %(PP + df.values[0,1] - df.values[0,2])
                elif col == 7: d = '%.2f' %(PP * 2 - df.values[0,2])
                elif col == 8: d = '%.2f' %PP
                elif col == 9: d = '%.2f' %(PP * 2 - df.values[0,1])
                elif col == 10: d = '%.2f' %(PP - df.values[0,1] + df.values[0,2])
                grid.SetCellValue(r, col, d)
        for r in range(len(rl)): grid.SetRowLabelValue(r+n+6-o,rl[r])
    def Load_Data_Frame(self, n):
        df_all = []
        p = [['86400', '3M'], ['300', '2d']] 
        symb = pd.DataFrame(pd.read_csv('TSE.csv'))
        for s in symb['Symbol']:
            param = {'q': s,'i': p[n][0],'x': "TSE",'p': p[n][1]}
            df = gf.get_price_data(param)
            df['T'] = s
            df['HiLo'] = 100 * (df['Close'] - df['Open']) / df['Open']
            df['GoR'] = df['Close'] > df['Open']
            df_all.append(df)
        dfg = pd.DataFrame()
        dfr = pd.DataFrame()
        num = len(df_all)
        for s in range(num):
            i = len(df_all[s].index) - 1
            if i < 10: continue
            nGreen, nRed, vGreen, vRed = 0,0,0,0
            hGreen, hRed, iGreen, iRed = 0,0,True,True
            while iGreen or iRed:
                if iGreen:
                    if df_all[s].values[i, 7]:
                        nGreen += 1
                        if hGreen < df_all[s].values[i, 6]:
                            hGreen = df_all[s].values[i, 6]
                    else: iGreen = False
                if iRed:
                    if not df_all[s].values[i, 7]:
                        nRed += 1
                        if hRed > df_all[s].values[i, 6]:
                            hRed = df_all[s].values[i, 6]
                    else: iRed = False
                i -= 1
                if i < 0: break
            vAvg20 = pd.Series(df_all[s]['Volume']).rolling(window=20).mean()
            df_all[s]['U'] = round(hGreen, 2)
            df_all[s]['D'] = round(-hRed, 2)
            df_all[s]['gBars'] = int(nGreen)
            df_all[s]['rBars'] = int(nRed)
            df_all[s]['Vg'] = vGreen / vAvg20
            df_all[s]['Vr'] = vRed / vAvg20
            dUp = df_all[s][['T','Close','gBars','U','Vg','Volume']]
            dDn = df_all[s][['T','Close','rBars','D','Vr','Volume']]
            if dfg.empty: dfg = dUp.tail(1)
            else: dfg = dfg.append(dUp.tail(1))
            if dfr.empty: dfr = dDn.tail(1)
            else: dfr = dfr.append(dDn.tail(1))
        dfg6 = dfg.sort_values('gBars', ascending=False).head(6)
        dfr6 = dfr.sort_values('rBars', ascending=False).head(6)
        return dfg6, dfr6            
if __name__ == "__main__":
    app = wx.App()
    win = Frame()
    win.Show()
    app.MainLoop()
This code needs TSE.csv as input containing the flowing:


Ok,

You need to learn how to read the error traceback.
It pointed directly to the error.
win was not defined in the method run as it was out of scope.

in order to make it work, you need to save win from the __init__ attributes to a variable that run can see,
thus in the code below:
self.win = win
and also refer to it as self.win in the methods that use it.
new code still doesn't run to finish, but has gotten past the error you were receiving:

import wx
import wx.grid
import pandas as pd
import googlefinance.client as gf
from threading import *


class RunThread(Thread):
    def __init__(self, event, win):
        self.win=win
        Thread.__init__(self)
        self.stopped = event
        self.start()

    def run(self):
        print('Loading 0,0 ..')
        self.win.Update_5M(0, 0)
        while True:
            print('Loading 1,12 ..')
            self.win.Update_5M(1, 12)
            self.stopped.wait(20)


class Frame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="Thread Crash", size=(530, 742), pos=(500, 100))
        wx.Panel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(sizer)
        self.grid = self.Create_Grid()
        stopFlag = Event()
        RunThread(stopFlag, self)

    def Update_5M(self, n, m):
        self.dfg, self.dfr = self.Load_Data_Frame(n)
        self.Update_Grid(self.dfr, self.grid, 'red', m)
        self.Update_Grid(self.dfg, self.grid, 'green', m)

    def Create_Grid(self):
        self.colno = 11
        self.colsz = [43, 40, 22, 40, 44, 60, 40, 40, 40, 40, 40]
        grid = wx.grid.Grid(self, size=(522, 700), pos=(0, 0))
        grid.CreateGrid(1, 11)
        grid.SetRowLabelSize(60)
        grid.SetLabelFont(wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.NORMAL))
        grid.SetDefaultCellAlignment(wx.ALIGN_RIGHT, wx.ALIGN_CENTRE)
        for col in range(self.colno):
            grid.SetColSize(col, self.colsz[col])
        return grid

    def Update_Grid(self, df_head, grid, gor, n):
        cols = grid.GetNumberCols()
        rows = grid.GetNumberRows()
        rl =
        for r in range(rows): rl.append(grid.GetRowLabelValue(r + n))
        for row in range(len(df_head.index)):
            r = row + n
            grid.InsertRows(r, 1, False)
            param = {'q': df_head.values[row, 0], 'i': "86400", 'x': "TSE", 'p': "5d"}
            df = gf.get_price_data(param).tail(1)
            o = 0
            if len(df) < 1:
                grid.DeleteRows(r, 1, False)
                r -= 1
                o += 1
                continue
            PP = (df.values[0, 1] + df.values[0, 2] + df.values[0, 3]) / 3
            for col in range(self.colno):
                if col != 2:
                    if n == 0:
                        if gor == 'green': grid.SetCellBackgroundColour(r, col, wx.Colour(row * 50, 200, row * 40))
                        if gor == 'red': grid.SetCellBackgroundColour(r, col, wx.Colour(200, row * 50, row * 40))
                    else:
                        if gor == 'green': grid.SetCellBackgroundColour(r, col, wx.Colour(row * 50, 255, row * 40))
                        if gor == 'red': grid.SetCellBackgroundColour(r, col, wx.Colour(255, row * 50, row * 40))
                if col == 2:
                    d = ('%.0f' % df_head.values[row, col])
                elif col == 0:
                    d = df_head.values[row, col]
                elif col == 5:
                    d = format(df_head.values[row, col], "8,d")
                elif col < 6:
                    d = ('%.2f' % df_head.values[row, col])
                elif col == 6:
                    d = '%.2f' % (PP + df.values[0, 1] - df.values[0, 2])
                elif col == 7:
                    d = '%.2f' % (PP * 2 - df.values[0, 2])
                elif col == 8:
                    d = '%.2f' % PP
                elif col == 9:
                    d = '%.2f' % (PP * 2 - df.values[0, 1])
                elif col == 10:
                    d = '%.2f' % (PP - df.values[0, 1] + df.values[0, 2])
                grid.SetCellValue(r, col, d)
        for r in range(len(rl)): grid.SetRowLabelValue(r + n + 6 - o, rl[r])

    def Load_Data_Frame(self, n):
        df_all =
        p = [['86400', '3M'], ['300', '2d']]
        symb = pd.DataFrame(pd.read_csv('TSE.csv'))
        for s in symb['Symbol']:
            param = {'q': s, 'i': p[n][0], 'x': "TSE", 'p': p[n][1]}
            df = gf.get_price_data(param)
            df['T'] = s
            df['HiLo'] = 100 * (df['Close'] - df['Open']) / df['Open']
            df['GoR'] = df['Close'] > df['Open']
            df_all.append(df)
        dfg = pd.DataFrame()
        dfr = pd.DataFrame()
        num = len(df_all)
        for s in range(num):
            i = len(df_all[s].index) - 1
            if i < 10: continue
            nGreen, nRed, vGreen, vRed = 0, 0, 0, 0
            hGreen, hRed, iGreen, iRed = 0, 0, True, True
            while iGreen or iRed:
                if iGreen:
                    if df_all[s].values[i, 7]:
                        nGreen += 1
                        if hGreen < df_all[s].values[i, 6]:
                            hGreen = df_all[s].values[i, 6]
                    else:
                        iGreen = False
                if iRed:
                    if not df_all[s].values[i, 7]:
                        nRed += 1
                        if hRed > df_all[s].values[i, 6]:
                            hRed = df_all[s].values[i, 6]
                    else:
                        iRed = False
                i -= 1
                if i < 0: break
            vAvg20 = pd.Series(df_all[s]['Volume']).rolling(window=20).mean()
            df_all[s]['U'] = round(hGreen, 2)
            df_all[s]['D'] = round(-hRed, 2)
            df_all[s]['gBars'] = int(nGreen)
            df_all[s]['rBars'] = int(nRed)
            df_all[s]['Vg'] = vGreen / vAvg20
            df_all[s]['Vr'] = vRed / vAvg20
            dUp = df_all[s][['T', 'Close', 'gBars', 'U', 'Vg', 'Volume']]
            dDn = df_all[s][['T', 'Close', 'rBars', 'D', 'Vr', 'Volume']]
            if dfg.empty:
                dfg = dUp.tail(1)
            else:
                dfg = dfg.append(dUp.tail(1))
            if dfr.empty:
                dfr = dDn.tail(1)
            else:
                dfr = dfr.append(dDn.tail(1))
        dfg6 = dfg.sort_values('gBars', ascending=False).head(6)
        dfr6 = dfr.sort_values('rBars', ascending=False).head(6)
        return dfg6, dfr6


if __name__ == "__main__":
    app = wx.App()
    win = Frame()
    win.Show()
    app.MainLoop()
try your best to finish, and come back if you get stuck.[/s][/s][/s][/s][/s][/s][/s][/s][/s][/s][/s][/s][/s][/s][/s][/s]
Thank you. I just did as you say but still crash. Did you try on your machine?
Pages: 1 2