Hello,
I have a problem with my wxPython based application. The application hangs and does not leave the MainLoop.
Let me first describe my setup. I have a windows MFC c++ application that calls a python program via the COM interface. This python program is a win32 COM server. This program does have a need for a GUI frontend based
on wxPython. In order to separate this GUI from my main c++/Python application I use the python multiprocessing.Process class to create a separate python process in which I run my wx.App based application. Below you can find my simplified code.
If I use ‘python.exe’ instead of ‘pythonw.exe’ in the
multiprocessing.set_executable statement, the wx.App based application terminates fine, i.e. its OnExit handler is called and the MainLoop finishes as expected. However, if I
use ‘pythonw.exe’ instead, this is not the case anymore. Neither OnExit is called nor is the MainLoop finished. However, the frame OnCloseFrame handler is still called. I did try to use Destroy() instead of Skip() but that doesn’t work either.
So my question is, do anyone has an explanation why the gui is hanging when I use ‘pythonw.exe’. Additionally, do you know a measure with which I can solve my issue.
Best,
Johannes
GuiProcess runs function creation_fun in its own process. Here it is function StartNumber
class GuiProcess(multiprocessing.Process):
def init(self, inQueue, outQueue, creation_fun, process_name = ‘GuiProcess’, *args, **kwargs):
self._app = None
self._inQueue = inQueue
self._outQueue = outQueue
self._creation_fun = creation_fun
multiprocessing.set_executable(os.path.join(dirPython,‘pythonw.exe’))
multiprocessing.Process.init(self, name = process_name)
self._args = tuple(args)
self._kwargs = dict(kwargs)
self.daemon = True
def run(self):
self._app = self._creation_fun(app_data, self._inQueue, self._outQueue, *self._args, **self._kwargs)
GuiApp uses helper GuiProcess to call function creation_fun in a new process
class GuiApp():
def init(self, data, creation_fun, callbacks, *args, **kwargs):
self.data = data
self.callbacks = callbacks
self.inQueue = multiprocessing.Queue() # push data into gui process
self.outQueue = multiprocessing.Queue() # receive data from gui process
self.gui_process = GuiProcess(self.inQueue, self.outQueue, creation_fun, ‘GuiProcess’, *args, **kwargs)
self.gui_process.start()
class StartNumberFrame(wx.Frame):
def init( self, msgDict, data, inQueue, outQueue, *args, **kwargs ):
self.Bind( wx.EVT_CLOSE, self.OnCloseFrame )
…
def OnCloseFrame( self, event ):
…
event.Skip()
class StartNumberApp(wx.App):
def init(self, msgDict, data, inQueue, outQueue):
wx.App.init(self, False)
def OnInit(self):
parent = GetCADdyParent()
frame = StartNumber.StartNumberFrame(self.msgDict, self.data, self.inQueue, self.outQueue, parent)
frame.Show(True)
self.SetTopWindow(frame)
return True
def OnExit(self):
…
This function creates a wx.App based instance and starts its main loop.
def StartNumber(data, inQueue, outQueue, *args, **kwargs):
app = StartNumberApp(msgDict, data, inQueue, outQueue)
app.MainLoop()
The main python application started from my MFC windows C++ program via COM
class ActRenumber(ActionBase):
def init(self, …):
self.app_start_number = GuiApp(…,StartNumber, …) # GuiApp takes function StartNumber which is finally responsible for the creation of the wxApp application run in a separate
process.