MainLoop() doesn't get terminated on close event if plugin instantiates its on MainLoop

Hello,

I recently started playing with wxPython but discovered an issue which I can’t solve.

I assume I’m doing something wrong but I don’t find any hint in the documentation how to solve this

or I just didn’t read the correct section yet.

My problem is the following.

Having a main application which loads external python code using imp module.

When such “plugin” code also has created a window my main application

doesn’t quit properly on exit anymore.

If I don’t run the “plugin” window, the main application quits as expected.

What I do is the following.

In main application

    for plug in self.getPlugins():
        print("Loading plugin " + plug["name"])
        subMenu = wx.Menu()
        pluginMenu.AppendSubMenu(subMenu,plug["name"])
       
        plugin = self.loadPlugin(plug)
        for func in plugin.getExportedFunctions():
            print 'func:{0}'.format(func)
            newItem = wx.MenuItem(subMenu, wx.ID_ANY, func)
            subMenu.AppendItem(newItem)
            self.Bind(wx.EVT_MENU, eval('plugin.{0}'.format(func)), newItem)

``

Which works ok - I do see the menu entries and the functions are executed fine.

But when a plugin has such a code

import wx

def getExportedFunctions():
return [‘run’, ‘show’]

def run(self):
print ‘test2 - run’
print ‘globals’
print ‘\r\n’.join([x for x in globals()])
print ‘locals’
print ‘\r\n’.join([x for x in locals()])

def show(self):
print ‘create wx.App’
app = wx.App(redirect=False)
print ‘calling myFrame’
myFrame(None)
print ‘entering mainloop’
app.MainLoop()
print ‘left mainloop’
app = None
print ‘returning from’
return

class myFrame(wx.Frame):

def __init__(self, parent=None):
    print 'constructor called'
    self.parent = parent
    wx.Frame.__init__(self, parent, wx.ID_ANY)

    self.Bind(wx.EVT_CLOSE,self.OnCloseWindow)

    self.Show()        
    self.Centre()

def __del__(self):
    print 'destructor called'
   
def OnCloseWindow(self, e):
    print "killing window"
    self.Destroy()

``

then the main app doesn’t quit properly which means I need to kill python process manually.

From the print statements it looks like this after starting main app.

Loading plugin test1
func:run
func:exit
func:show
Loading plugin test2
func:run
func:show

``

Now when clicking on show from menu test2 the window appears and print statements are

create wx.App
calling myFrame
constructor called
entering mainloop

``

When closing the plugin window by clicking the x button I get the following

killing window
destructor called

``

as you see, I don’t get the left mainloop and returning from print statements but window disappeared.

When closing main application I do get

left mainloop
returning from

``

and main application disappears as well but python process is still running

because the MainLoop() of my main app is still active.

So what am I doing wrong here?

Thank you

Hubert

Hubert Mayr wrote:

So what am I doing wrong here?

Creating more than one wx.App object is never supported in the same
process. Any frames created in plug-ins will automatically run under
the main loop of your first wx.App, so there is no need to create a
second one and as you are seeing, it leads to completely unpredictable
behaviour.

···

--
James Scholes
http://twitter.com/JamesScholes

Creating more than one wx.App object is never supported in the same

process. Any frames created in plug-ins will automatically run under

the main loop of your first wx.App, so there is no need to create a

second one and as you are seeing, it leads to completely unpredictable

behaviour.


James Scholes

http://twitter.com/JamesScholes

I see, makes sense thank you for clarification.

Hubert

Also I think you are overriding the __ del __ method incorrectly.

It think you need to call its super __del__(). Or at least it would be
prudent.

def __del__(self):
    print('reference decrement and deletion')
    return wx.Frame.__del__(self)

Sorry for late response but I wasn’t informed about new reply.
You are right, should call either super() or wx.Frame…

Just did it to see if it got executed and deleted it afterwards again.

Thank you

Hubert

···

On Tuesday, May 31, 2016 at 9:16:36 PM UTC+2, DevPlayer wrote:

Also I think you are overriding the __ del __ method incorrectly.

It think you need to call its super del(). Or at least it would be prudent.

def del(self):

print(‘reference decrement and deletion’)

return wx.Frame.del(self)