Running wxPython app from embedded interpreter

Hello,

I have a wxPython app that works fine when I run with python.exe, however I would like to be able to run with the embedded Python interpreter in my C++ application. When I run the app the first time, it works fine. But when I close the app and try to run it again I get this exception:

Traceback (most recent call last):

File “D:\MyApp\MyApp.py”, line 10, in

frame = MyFrame(None)

File “D:\MyApp\MyApp.py”, line 6, in init

wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"MyApp" )

File “D:\App\bin\x64\Debug\lib\site-packages\wx-3.0-msw\wx_windows.py”, line 580, in init

_windows_.Frame_swiginit(self,_windows_.new_Frame(*args, **kwargs))

wx._core.PyNoAppError: The wx.App object must be created first!

Here is the code I’m using to test this issue:

import wx

class MyFrame ( wx.Frame ):

def __init__( self, parent ):

    wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"MyApp" )

app = wx.App(False)

frame = MyFrame(None)

frame.Show()

app.MainLoop()

Any idea how to get around this?

Thanks,

Ian

You probably want to start (and keep a reference to) a wx.App() at the
startup of the embedded Python interpreter, and have any frames you create
access that. If you're using multiple interpreters, you probably need one
wxApp instance per interpreter, though I've not ever tried that myself.

That is, don't let app.MainLoop() end, just create wx.Frame()s and show
them.

--Matt

···

On Tue, Jul 25, 2017 at 7:18 PM, Ian Abshire <ianabshire@gmail.com> wrote:

Hello,

I have a wxPython app that works fine when I run with python.exe, however
I would like to be able to run with the embedded Python interpreter in my
C++ application. When I run the app the first time, it works fine. But when
I close the app and try to run it again I get this exception:

Traceback (most recent call last):
  File "D:\MyApp\MyApp.py", line 10, in <module>
    frame = MyFrame(None)
  File "D:\MyApp\MyApp.py", line 6, in __init__
    wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"MyApp" )
  File "D:\App\bin\x64\Debug\lib\site-packages\wx-3.0-msw\wx\_windows.py"
, line 580, in __init__
    _windows_.Frame_swiginit(self,_windows_.new_Frame(*args, **kwargs))
wx._core.PyNoAppError: The wx.App object must be created first!

Here is the code I'm using to test this issue:

import wx

class MyFrame ( wx.Frame ):

    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"MyApp"
)

app = wx.App(False)
frame = MyFrame(None)
frame.Show()
app.MainLoop()

Any idea how to get around this?

Matt Newville wrote:

You may also want to call the_app.SetExitOnFrameDelete(False) so the MainLoop doesn’t terminate when all top-level windows have been closed.
Then you can still create new frames or dialogs later on in the program’s lifetime without worrying about whether the app object and event loop are still alive or not.

···

On Tue, Jul 25, 2017 at 7:18 PM, Ian Abshire ianabshire@gmail.com
wrote:

Hello,

I
have a wxPython app that works fine when I run with python.exe, however
I would like to be able to run with the embedded Python interpreter in my C++ application. When I run the app the first time, it works fine. But when I close the app and try to run it again I get this exception:

Traceback ( most
recent call last):

File “D:\MyApp\MyApp.py”, line 10, in

frame = MyFrame(None)

File “D:\MyApp\MyApp.py”, line 6, in init

wx.Frame.__init__ ( self,  parent, id = wx.ID_ANY, title =

u"MyApp" )

File “D:\App\bin\x64\Debug\lib\site-packages\wx-3.0-msw\wx_windows.py”, line 580, in init

_windows_.Frame_swiginit(self,_windows_.new_Frame(*args, **kwargs))

wx._core.PyNoAppError: The wx.App object must be created first!

Here
is the code I’m using to test this issue:

import wx

class MyFrame ( wx.Frame ):

def __init__( self, parent ):

    wx.Frame.__init__ ( se lf, parent, id = wx.ID_ANY, title =

u"MyApp" )

app = wx.App(False)

frame = MyFrame(None)

frame.Show()

app.MainLoop()

Any idea how to get around this?

You
probably want to start (and keep a reference to) a wx.App() at the startup of the embedded Python interpreter, and have any frames you create access that. If you’re using multiple interpreters, you probably
need one wxApp instance per interpreter, though I’ve not ever tried that myself.

That is, don’t let app.MainLoop() end, just create wx.Frame()s and show them.

Thank you for your suggestions! I will give them a try.

A few new questions come to mind now:

  • If I start an instance of wx.App() when the embedded Python interpreter starts, how do I make the frames access that instance of the app? If the Python program calls wx.App() again will it throw an exception?

  • About MainLoop(), if I call SetExitOnFrameDelete(False), then MainLoop() will not return when the frame is destroyed, correct? If this is so, then how can I create and show new frames? Do I need to start MainLoop() on a separate thread?

Thanks again for you help!

Ian

···

On Thursday, July 27, 2017 at 3:36:09 PM UTC-7, Robin Dunn wrote:

Matt Newville wrote:

On Tue, Jul 25, 2017 at 7:18 PM, Ian Abshire ianab...@gmail.com > > wrote:

Hello,

I
have a wxPython app that works fine when I run with python.exe, however
I would like to be able to run with the embedded Python interpreter in my C++ application. When I run the app the first time, it works fine. But when I close the app and try to run it again I get this exception:

Traceback ( most
recent call last):

File “D:\MyApp\MyApp.py”, line 10, in

frame = MyFrame(None)

File “D:\MyApp\MyApp.py”, line 6, in init

wx.Frame.__init__ ( self,  parent, id = wx.ID_ANY, title =

u"MyApp" )

File “D:\App\bin\x64\Debug\lib\site-packages\wx-3.0-msw\wx_windows.py”, line 580, in init

_windows_.Frame_swiginit(self,_windows_.new_Frame(*args, **kwargs))

wx._core.PyNoAppError: The wx.App object must be created first!

Here
is the code I’m using to test this issue:

import wx

class MyFrame ( wx.Frame ):

def __init__( self, parent ):

    wx.Frame.__init__ (  self, parent, id = wx.ID_ANY, title =

u"MyApp" )

app = wx.App(False)

frame = MyFrame(None)

frame.Show()

app.MainLoop()

Any idea how to get around this?

You
probably want to start (and keep a reference to) a wx.App() at the startup of the embedded Python interpreter, and have any frames you create access that. If you’re using multiple interpreters, you probably
need one wxApp instance per interpreter, though I’ve not ever tried that myself.

That is, don’t let app.MainLoop() end, just create wx.Frame()s and show them.


Robin Dunn

Software Craftsman

http://wxPython.org

You may also want to call the_app.SetExitOnFrameDelete( False) so the MainLoop doesn’t terminate when all top-level windows have been closed.
Then you can still create new frames or dialogs later on in the program’s lifetime without worrying about whether the app object and event loop are still alive or not.

A few new questions come to mind now:
- If I start an instance of wx.App() when the embedded Python interpreter
starts, how do I make the frames access that instance of the app?

wx is dsigned to have only one App instance -- so they a new FRame will
simply use the one that's running.

If you ever need a refernce to the App, there is wx.GetApp() (or something
like that...)

If the Python program calls wx.App() again will it throw an exception?

yes. I think so -- at least it used to -- it could be a no-op.

- About MainLoop(), if I call SetExitOnFrameDelete(False), then MainLoop()
will not return when the frame is destroyed, correct? If this is so, then
how can I create and show new frames? Do I need to start MainLoop() on a
separate thread?

you can create new Frames in an event handler.

wx.CallAfter() may be the easiest way to do this from an arbitrary part of
the code.

-CHB

Matt Newville wrote:

···

On Fri, Jul 28, 2017 at 10:13 AM, Ian Abshire <ianabshire@gmail.com> wrote:

On Tue, Jul 25, 2017 at 7:18 PM, Ian Abshire <ianab...@gmail.com> wrote:

Hello,

I have a wxPython app that works fine when I run with python.exe,
however I would like to be able to run with the embedded Python interpreter
in my C++ application. When I run the app the first time, it works fine.
But when I close the app and try to run it again I get this exception:

Traceback (most recent call last):
  File "D:\MyApp\MyApp.py", line 10, in <module>
    frame = MyFrame(None)
  File "D:\MyApp\MyApp.py", line 6, in __init__
    wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"MyApp" )
  File "D:\App\bin\x64\Debug\lib\site-packages\wx-3.0-msw\wx
\_windows.py", line 580, in __init__
    _windows_.Frame_swiginit(self,_windows_.new_Frame(*args, **kwargs))
wx._core.PyNoAppError: The wx.App object must be created first!

Here is the code I'm using to test this issue:

import wx

class MyFrame ( wx.Frame ):

    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u
"MyApp" )

app = wx.App(False)
frame = MyFrame(None)
frame.Show()
app.MainLoop()

Any idea how to get around this?

You probably want to start (and keep a reference to) a wx.App() at the
startup of the embedded Python interpreter, and have any frames you create
access that. If you're using multiple interpreters, you probably need one
wxApp instance per interpreter, though I've not ever tried that myself.

That is, don't let app.MainLoop() end, just create wx.Frame()s and show
them.

You may also want to call `the_app.SetExitOnFrameDelete(False)` so the
MainLoop doesn't terminate when all top-level windows have been closed.
Then you can still create new frames or dialogs later on in the program's
lifetime without worrying about whether the app object and event loop are
still alive or not.

--
Robin Dunn
Software Craftsman
http://wxPython.org

--
You received this message because you are subscribed to the Google Groups
"wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to wxpython-users+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

When you load your wx application into a py.shell the MainLoop is already running. In my experience (admittedly running under Linux which is different) you cannot do an import of wx into wx. In fact it isn’t necessary. Just type wx. (use the dot) and you will see the already imported wx attributes in the drop down.

Your answer is to instantiate a py.shell in a panel, either as part or your app, or as a child window of your application. There are some sliding panel examples out there.

Bizarrely, you might have success NOT doing the import wx at the start of your application. Comment it out and see if that helps. Please post your result.

···

On Wednesday, July 26, 2017 at 1:18:43 AM UTC+1, Ian Abshire wrote:

Hello,

I have a wxPython app that works fine when I run with python.exe, however I would like to be able to run with the embedded Python interpreter in my C++ application. When I run the app the first time, it works fine. But when I close the app and try to run it again I get this exception:

Traceback (most recent call last):

File “D:\MyApp\MyApp.py”, line 10, in

frame = MyFrame(None)

File “D:\MyApp\MyApp.py”, line 6, in init

wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"MyApp" )

File “D:\App\bin\x64\Debug\lib\site-packages\wx-3.0-msw\wx_windows.py”, line 580, in init

_windows_.Frame_swiginit(self,_windows_.new_Frame(*args, **kwargs))

wx._core.PyNoAppError: The wx.App object must be created first!

Here is the code I’m using to test this issue:

import wx

class MyFrame ( wx.Frame ):

def __init__( self, parent ):

    wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"MyApp" )

app = wx.App(False)

frame = MyFrame(None)

frame.Show()

app.MainLoop()

Any idea how to get around this?

Thanks,

Ian

If you would like to be able to use your application code both embedded
and standalone I would suggest something like:

if not 'wx' in dir(): # Is the namespace already there?
     import wx

And don't forget to make sure that your wx.App() in the python code is
conditional on __name__ == "__main__" as you must always have exactly
ONE wx.App.

···

On 31/07/2017 23:49, brad@bradcan.homelinux.com wrote:

When you load your wx application into a py.shell the MainLoop is
already running. In my experience (admittedly running under Linux which
is different) you cannot do an import of wx into wx. In fact it isn't
necessary. Just type wx. (use the dot) and you will see the already
imported wx attributes in the drop down.

Your answer is to instantiate a py.shell in a panel, either as part or
your app, or as a child window of your application. There are some
sliding panel examples out there.

Bizarrely, you might have success NOT doing the import wx at the start
of your application. Comment it out and see if that helps. Please post
your result.

--
Steve (Gadget) Barnes
Any opinions in this message are my personal opinions and do not reflect
those of my employer.

---
This email has been checked for viruses by AVG.

Something like this example. Your application goes in the MainFrame. The example is just a button which pops up a shell. The popup shell behaves just like any other window. It already has the reference to app. Don’t do import into the shell, specifically you do NOT need to import wx. Importing wx into the shell will cause you much grief. Hope this helps.

import wx
from wx import py

Imports for the shell go here!

class ShellFrame(wx.Frame):
def init(self):
wx.Frame.init(self, None, title=“py shell”, size=(600,300))
self.panel = wx.Panel(self)
self.shell = py.shell.Shell(self.panel, -1)
self.panel.Bind(wx.EVT_SIZE, self.OnSize)

def OnSize(self, evt):
    size = self.panel.GetClientSize()
    self.shell.SetSize(size)

class MainFrame(wx.Frame):
def init(self, parent, title):
wx.Frame.init(self, None, title=title, pos=(200,200), size=(200,100))
self.shell = None
self.layout()
self.Bind(wx.EVT_CLOSE, self.OnClose)
self.Show()

def layout(self):
    btn = wx.Button(self, label='open shell', size=(100,50))
    btn.Bind(wx.EVT_BUTTON, self.OnButton)
    sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
    sizer_1.Add(btn, 0, wx.ALIGN_CENTER_VERTICAL, 0)
    sizer_2 = wx.BoxSizer(wx.VERTICAL)
    sizer_2.Add(sizer_1, 1, wx.ALIGN_CENTER, 0)
    self.SetSizer(sizer_2)
    self.Layout()

def OnClose(self, event):

… if self.shell and self.shell.IsShownOnScreen():
self.shell.Close()
event.Skip()

def OnButton(self, event):
    self.shell = ShellFrame()
    self.shell.Show()

app = wx.App(False)
MainFrame(None, title=‘E.G. Shell’)
app.MainLoop()

···

Any idea how to get around this?

Thanks,

Ian