How to load a heavy model when using MVC design pattern

前端 未结 3 1256
终归单人心
终归单人心 2021-01-17 06:34

I\'m building an application with wxPython and a Deep Learning model that I created using Tensorflow. The design pattern that I\'m using is MVC. My problem is that the deep

3条回答
  •  旧时难觅i
    2021-01-17 06:51

    You could use the _thread module and the PyPubSub module to keep the main thread completely functional during the loading of the model.

    However, keep in mind that if you have a wx.Button in the GUI bound to method A and method A requires the full model to be loaded to properly run, then users will be able to click the wx.Button and the program will probably hang because the model is still not fully loaded. If this is the case, you could use the methods Disable() (while the model is being loaded) and Enable() (after the model is loaded) to prevent this.

    Code with comments (####).

    import wx
    import time
    import _thread
    from pubsub import pub
    
    class Model:
        def __init__(self):
            '''This part is simulating the loading of tensorflow'''
            x = 0
            while x < 15:
                time.sleep(1)
                print(x)
                #### This is how you broadcast the 'Loading' message 
                #### from a different thread.
                wx.CallAfter(pub.sendMessage, 'Loading', x=x)
                x += 1
            #### The same as before
            wx.CallAfter(pub.sendMessage, 'Loading', x=x)
    
    class View(wx.Frame):
        def __init__(self, parent, title):
            super(View, self).__init__(parent, title=title, size=(400, 400))
            self.InitUI()
    
        def InitUI(self):
            # Defines the GUI controls
            #### It needed to set the size of the panel to cover the frame
            #### because it was not covering the entire frame before
            masterPanel = wx.Panel(self, size=(400, 400))
            masterPanel.SetBackgroundColour("gold")
            self.vbox = wx.BoxSizer(wx.VERTICAL)
            self.fgs = wx.FlexGridSizer(6, 2, 10, 25)
            id = wx.StaticText(self, label="ID:")
            firstName = wx.StaticText(self, label="First name:")
            lastName = wx.StaticText(self, label="Last name:")
            self.idTc = wx.TextCtrl(self)
            self.firstNameTc = wx.TextCtrl(self)
            self.lastNameTc = wx.TextCtrl(self)
            self.fgs.AddMany([id, (self.idTc, 1, wx.EXPAND),
                             firstName, (self.firstNameTc, 1, wx.EXPAND),
                             lastName, (self.lastNameTc, 1, wx.EXPAND)])
            self.vbox.Add(self.fgs, proportion=1, flag=wx.ALL | wx.EXPAND,
       border=15)
            self.SetSizer(self.vbox)
            self.vbox.Fit(self)
            self.Layout()
    
            #### Create status bar to show loading progress. 
            self.statusbar = self.CreateStatusBar(1)
            self.statusbar.SetStatusText('Loading model')
            #### Set the size of the window because the status bar steals space
            #### in the height direction.
            self.SetSize(wx.DefaultCoord, 160)
            #### Subscribe the class to the message 'Loading'. This means that every
            #### time the meassage 'Loading' is broadcast the method 
            #### ShowLoadProgress will be executed.
            pub.subscribe(self.ShowLoadProgress, 'Loading')
            #### Start the thread that will load the model
            _thread.start_new_thread(self.LoadModel, ('test',))
    
        def LoadModel(self, test):
            """
            Load the Model
            """
            #### Change depending on how exactly are you going to create/load the 
            #### model
            self.model = Model()
    
        def ShowLoadProgress(self, x):
            """
            Show the loading progress 
            """
            if x < 15:
                self.statusbar.SetStatusText('Loading progress: ' + str(x))
            else:
                self.statusbar.SetStatusText('All loaded')
    
    class Controller:
        def __init__(self):
            self.view = View(None, title='Test')
            self.view.Show()
            #### The line below is not needed now because the model is 
            #### loaded now from the thread started in View.InitUI
            #self.model = Model()
    
    def main():
        app = wx.App()
        controller = Controller()
        app.MainLoop()
    
    if __name__ == '__main__':
        main()
    

    If you load the model from a method inside class View then you will not need the PyPubSub module because you could just call wx.CallAfter(self.ShowLoadProgress, x)

提交回复
热议问题