Manually trigger Close application and other events

I’m working on PythonTurtle, which is an interactive “Learn Python” program with an embedded interpreter.

When I type the Python interpreter’s exit() command I want to shut down the application. This seems to be easier said than done. I’ve tried:

  • raise SystemExit(), which does nothing (seems to be caught by wxPython)
  • os._exit(0), the brute force way, makes the application window hang (showing an hour glass)
  • wx.Abort(), which behaves the same way as os._exit(0)
  • <xwFrame>.Close(force=True), which does nothing (though returning True)
  • post a wx.ID_EXIT event à la wx.PostEvent(...), which you can see in PR #133 on GitHub.

All attempts were unsuccessful.

Interestingly, I’ve found solutions mentioning wxFrame.Close and wxFrame.Destroy on StackOverflow, but none of them work for me.

As an alternative, I thought about firing the event that mimics the user action of selecting “File > Exit”, even though that feels like a cumbersome workaround. However, I’d need a similar thing for displaying a help screen, which should happen when the user types help() in the Python interpreter: Calling the show_help() method directly that is bound to the button produces an exception as if some attributes were lost on the frame object.

The code is all public and for the two problems there is an isolated pull request.

What do I have to do to implement the wanted behavior?

Thanks in advance for any hints, Peter

When I type the Python interpreter’s exit() command I want to shut down the application. This seems to be easier said than done. I’ve tried:

Interestingly, I’ve found solutions mentioning wxFrame.Close and wxFrame.Destroy on StackOverflow, but none of them work for me.

When the primary window is closed, the application exits. That’s how wxWindows is designed. Is it possible the window you’re triggering is not the applications “primary” window?

···

On Mar 31, 2019, at 3:25 AM, Peter Bittner peter.bittner@gmail.com wrote:


Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

Try:

theapp = wx.GetApp()

theapp.SetExitOnFrameDelete(True)

theapp.TopWindow.Close()

(This should call any cleaning up that closing the top window would normally do)!

Steve (Gadget) Barnes

···

From: wxpython-users@googlegroups.com wxpython-users@googlegroups.com
On Behalf Of Tim Roberts
Sent: 31 March 2019 19:43
To: ‘Khanh D Dang’ via wxPython-users wxpython-users@googlegroups.com
Subject: Re: [wxPython-users] Manually trigger Close application and other events

On Mar 31, 2019, at 3:25 AM, Peter Bittner peter.bittner@gmail.com wrote:

When I type the Python interpreter’s exit() command I want to shut down the application. This seems to be easier said than done. I’ve tried:

Interestingly, I’ve found solutions mentioning wxFrame.Close and wxFrame.Destroy

on StackOverflow
, but none of them work for me.

When the primary window is closed, the application exits. That’s how wxWindows is designed. Is it possible the window you’re triggering is not the applications “primary” window?


Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.


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.

Hi Peter,

···

On Sun, Mar 31, 2019 at 11:40 AM Peter Bittner peter.bittner@gmail.com wrote:

I’m working on PythonTurtle, which is an interactive “Learn Python” program with an embedded interpreter.

When I type the Python interpreter’s exit() command I want to shut down the application. This seems to be easier said than done. I’ve tried:

  • raise SystemExit(), which does nothing (seems to be caught by wxPython)
  • os._exit(0), the brute force way, makes the application window hang (showing an hour glass)
  • wx.Abort(), which behaves the same way as os._exit(0)
  • <xwFrame>.Close(force=True), which does nothing (though returning True)
  • post a wx.ID_EXIT event à la wx.PostEvent(...), which you can see in PR #133 on GitHub.

All attempts were unsuccessful.

Interestingly, I’ve found solutions mentioning wxFrame.Close and wxFrame.Destroy on StackOverflow, but none of them work for me.

As an alternative, I thought about firing the event that mimics the user action of selecting “File > Exit”, even though that feels like a cumbersome workaround. However, I’d need a similar thing for displaying a help screen, which should happen when the user types help() in the Python interpreter: Calling the show_help() method directly that is bound to the button produces an exception as if some attributes were lost on the frame object.

The code is all public and for the two problems there is an isolated pull request.

What do I have to do to implement the wanted behavior?

Thanks in advance for any hints, Peter

I think you need to replace builtins.exit (and builtins.quit) in your embedded instance of the Interpreter with function that destroy the main window. Specifically, you probably want to put your custom functions for “exit”, “quit”, and maybe “help” and “license” in the locals dict when creating the

InteractiveInterpreter().

–Matt

That’s what the PR actually does!

Thanks for pointing out that there is also quit()!

Peter

···

Am Sonntag, 31. März 2019 20:59:39 UTC+2 schrieb Matt Newville:

Hi Peter,

I think you need to replace builtins.exit (and builtins.quit) in your embedded instance of the Interpreter with function that destroy the main window. Specifically, you probably want to put your custom functions for “exit”, “quit”, and maybe “help” and “license” in the locals dict when creating the

InteractiveInterpreter().

–Matt

Thanks Steve,

I’ve tried the code and it actually does … nothing. :frowning:

Maybe the TopWindow is not the actual top frame we’re seeing. I’m not sure. There is really only a single frame, hmm. Any idea how I can troubleshoot this?

When I add thisapp.Destroy() after the instructions you suggest I get an interesting behavior: The application window doesn’t close, but at the next time I call the function wx.GetApp() returns None. So, “something” happened, but it wasn’t “shutting down the application”. Hmmm…

Peter

···

Am Sonntag, 31. März 2019 20:52:02 UTC+2 schrieb Gadget Steve:

Try:

theapp = wx.GetApp()

theapp.SetExitOnFrameDelete(True)

theapp.TopWindow.Close()

(This should call any cleaning up that closing the top window would normally do)!

Steve (Gadget) Barnes

From: wxpytho...@googlegroups.com wxpytho...@googlegroups.com
On Behalf Of Tim Roberts
Sent: 31 March 2019 19:43
To: ‘Khanh D Dang’ via wxPython-users wxpytho...@googlegroups.com
Subject: Re: [wxPython-users] Manually trigger Close application and other events

On Mar 31, 2019, at 3:25 AM, Peter Bittner peter....@gmail.com wrote:

When I type the Python interpreter’s exit() command I want to shut down the application. This seems to be easier said than done. I’ve tried:

Interestingly, I’ve found solutions mentioning wxFrame.Close and wxFrame.Destroy

on StackOverflow
, but none of them work for me.

When the primary window is closed, the application exits. That’s how wxWindows is designed. Is it possible the window you’re triggering is not the applications “primary” window?


Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.


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
wxpytho...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

I figured this behavior may all be related to the fact that we’re using multiprocessing. And this doesn’t play nicely, or at least not intuitively straight-forward, with wxPython.

Is that an information that can help getting my implementation ironed out correctly?

Peter

···

Am Sonntag, 31. März 2019 22:22:47 UTC+2 schrieb Peter Bittner:

Thanks Steve,

I’ve tried the code and it actually does … nothing. :frowning:

Maybe the TopWindow is not the actual top frame we’re seeing. I’m not sure. There is really only a single frame, hmm. Any idea how I can troubleshoot this?

When I add thisapp.Destroy() after the instructions you suggest I get an interesting behavior: The application window doesn’t close, but at the next time I call the function wx.GetApp() returns None. So, “something” happened, but it wasn’t “shutting down the application”. Hmmm…

Peter

Peter,

What I do in my multiprocessing application is to keep track of all of the PIDs and have an OnExit handler terminate them all, (and wait a short time for them to finish), before exit.

Steve

On Behalf Of Peter Bittner

···

I figured this behavior may all be related to the fact that we’re using

multiprocessing
. And this
doesn’t play nicely
, or at least not intuitively straight-forward, with wxPython.

Is that an information that can help getting my implementation ironed out correctly?

Peter

Am Sonntag, 31. März 2019 22:22:47 UTC+2 schrieb Peter Bittner:

Thanks Steve,

I’ve tried the code and it actually does … nothing. :frowning:

Maybe the TopWindow is not the actual top frame we’re seeing. I’m not sure. There is really only a single frame, hmm. Any idea how I can troubleshoot this?

When I add thisapp.Destroy() after the instructions you suggest I get an interesting behavior: The application window doesn’t close, but at the next time I call the function wx.GetApp() returns None. So,
“something” happened, but it wasn’t “shutting down the application”. Hmmm…

Peter


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.

Steve,

that sounds like a plan. How do you keep track of the PIDs? Can you give an example (as in code)?

Imagine you have a parent that forks off a child, and the child now invokes wx.Exit(). That makes the child process die. The parent windows (a wx.Frame) is still responsive, and I can operated the menu to end the application. – How can I, instead, make the parent process die? Or ask it to kill itself.

Peter

···

Am Montag, 1. April 2019 00:17:30 UTC+2 schrieb Gadget Steve:

Peter,

What I do in my multiprocessing application is to keep track of all of the PIDs and have an OnExit handler terminate them all, (and wait a short time for them to finish), before exit.

Steve

As it stands the problem is that I have a child process (the Python interpreter in the application window) that asks the parent process (the parent wx.Frame) to close itself, which it probably can honor for some reason, maybe related to the fact that the child is making the request.

What if I post an event that mimics the user going to “File > Exit” in the application window (the wx.MenuBar in the parent wx.Frame). How can I do that?

I would need to do the same operation for opening the help screen too, anyway. Simply calling self.parent_window.show_help() doesn’t work without an Exception later down the line.

Peter

···

Am Montag, 1. April 2019 01:10:49 UTC+2 schrieb Peter Bittner:

Steve,

that sounds like a plan. How do you keep track of the PIDs? Can you give an example (as in code)?

Imagine you have a parent that forks off a child, and the child now invokes wx.Exit(). That makes the child process die. The parent windows (a wx.Frame) is still responsive, and I can operated the menu to end the application. – How can I, instead, make the parent process die? Or ask it to kill itself.

Peter

Am Montag, 1. April 2019 00:17:30 UTC+2 schrieb Gadget Steve:

Peter,

What I do in my multiprocessing application is to keep track of all of the PIDs and have an OnExit handler terminate them all, (and wait a short time for them to finish), before exit.

Steve

Hi Peter,

I can’t post the actual code that I use in my work for obvious reasons but basically, (exact details vary on how the subprocesses are launched):

in init(self) of the top level process

self.subprocesses =

in all of the start subprocess methods

self.subprocesses.append(new_process_pid) # All of the methods of launching subprocesses have some mechanism for getting the PID

in the call back from the subprocess,

this is where you could get clever!

self.subprocesses.remove(pid) # The callback gets the PID as a parameter

in the top level process OnExit method

for pid in self.subprocesses:

call the halt/stop/exit for that pid

Re you help problem it sounds like you are calling the self.parent_window.show_help() without an event, (or dummy event), or the event is lacking some detail
possibly the parent window that is relied on later. What exactly is the exception it should show what is missing?

Hope that is some help.

Steve

On Behalf Of Peter Bittner

···

As it stands the problem is that I have a child process (the Python interpreter in the application window) that asks the parent process (the parent wx.Frame) to close itself, which it probably can honor for some
reason, maybe related to the fact that the child is making the request.

What if I post an event that mimics the user going to “File > Exit” in the application window (the

wx.MenuBar in the parent wx.Frame
). How can I do that?

I would need to do the same operation for

opening the help screen
too, anyway. Simply calling self.parent_window.show_help() doesn’t work without an Exception later down the line.

Peter

Am Montag, 1. April 2019 01:10:49 UTC+2 schrieb Peter Bittner:

Steve,

that sounds like a plan. How do you keep track of the PIDs? Can you give an example (as in code)?

Imagine you have a parent that forks off a child, and the child now invokes wx.Exit(). That makes the child process die. The parent windows (a wx.Frame) is still responsive, and I can operated the menu to
end the application. – How can I, instead, make the parent process die? Or ask it to kill itself.

Peter

Am Montag, 1. April 2019 00:17:30 UTC+2 schrieb Gadget Steve:

Peter,

What I do in my multiprocessing application is to keep track of all of the PIDs and have an OnExit handler terminate them all, (and wait a short time for them to finish), before exit.

Steve


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.

All the window handles, event loop, and all other UI-related elements are NOT inherited by the child process. (There may be an object but it is not connected to the original UI element.) It’s not completely clear from your descriptions thus far if you are aware of that or not. In case you’re not, you can not expect any wx thing that crosses the process boundary to work as if they were in the same process. In other words, if the parent process needs the UI elements in the child process to do something then you can’t just use the original object in the parent process to do it. Instead you need a non-UI way to send a message to the child and then have the child do it to itself. The multiprocessing module has a few ways to do that, and there are others too. Or if all you need to do is tell the child to terminate then using kill as Steve suggests is okay too, although you may want to have the child process catch those signals so they can shut down cleanly (flushing and closing files, etc.) if not doing so could cause problems.

···

On Sunday, March 31, 2019 at 2:52:26 PM UTC-7, Peter Bittner wrote:

I figured this behavior may all be related to the fact that we’re using multiprocessing. And this doesn’t play nicely, or at least not intuitively straight-forward, with wxPython.

Is that an information that can help getting my implementation ironed out correctly?

Robin