-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
[Bug]: Embedded Python uncatchable hard exit on closing last matplotlib window. #27147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Do you have the same problem with any other GUI backed? |
Currently no it is not a problem with the QtAgg backend. I just tried it
both on macOS Ventura 13.6 Apple Silicon with PyQt6, and on Windows 10 with
PyQt5. In both cases, they behaved as I hoped. Unfortunately on macOS,
the MacOSX backend is the default even with PyQt installed, so a user has
to know to set the backend or they will be surprised. I had worked around
it by forcing the backend to 'Agg' but that disables any GUI usage. At one
point I believe the Qt backend did exit on Windows (or crashed) which is
why I went to the step of attempting to load matplotlib after
Py_Initialize() and setting backend to 'Agg'
…On Thu, Oct 19, 2023 at 12:52 PM Thomas A Caswell ***@***.***> wrote:
Do you have the same problem with any other GUI backed?
—
Reply to this email directly, view it on GitHub
<#27147 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAOTME2SJJAF7DNT2HMTNFDYAFLGVAVCNFSM6AAAAAA6HJGIOSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONZRGM3TENBVG4>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Do you have a minimal example application you can give us to try and run this locally with?
|
It may take me a little bit, I’m sure I have a stand-alone embedded program
lying around, but it may be a day or two.
…On Thu, Oct 19, 2023 at 3:40 PM Greg Lucas ***@***.***> wrote:
Do you have a minimal example application you can give us to try and run
this locally with?
# Embed Python into a minimal application, run application
# from the embedded python scripting, run the script.
# Such as running through PyRun_SimpleString("code"); (not an interactive shell)
—
Reply to this email directly, view it on GitHub
<#27147 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAOTME6DERFI6UA2B4BTHHDYAF6ZRAVCNFSM6AAAAAA6HJGIOSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONZRGU4TQNZVGA>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Xcode Objective C++ project that creates a main window GUI with a single pushbutton. Push the button, and it runs the Python code that runs matplotlib which raises a window. Close the matplotlib window and the app crashes. Python Code run is within AppController.mm file. Inside is a #define MACOSX_BACKEND 1 to choose between 2 python scripts to submit to the embedded Python. The first runs Matplotlib without specifying a backend so it gets the 'macosx' backend. setting it to 0 runs the same code except the first thing it does is set the backend to 'PyAgg'. The 'MacOSX' backend crashes, while the 'PyAgg' backend lets you. close the window, and click the button, close the window, click the button,..., repeat, ... My current environment is macOS Ventura 13.6 Apple Silicon, Xcode 15, Python 3.11.5 ( use PyQt6 on Apple Silicon Mac since PyQt5 wouldn't install ) App creates a Window with a button click me. The button's action runs the Python code |
I set the build's minimum required OS to 11.0 so it should build an run on macOS 11.0 or newer (Intel or Apple Silicon) |
Even simpler example, single file can be compiled at the command line:
|
When I run when the app first opens I get:
(Along with what appears to be a stack trace) We have this message here: Lines 529 to 530 in fcd5bb1
I am able to make that warning go away by swapping the order of those two lines (so that the view is attached to the window before it is set as the first responder. However, that does not actually change any behavior. I am also seeing two more errors:
The first shows up when the window opens, the second when it closes. Neither matplotlib, nor the example app appear to make any reference to metallib, so not sure where that is being triggered. Some quick searching seems to indicate that the second is most often noise and not a real problem. Neither show up in the qtagg case. Now, I honestly don't know how to do it with the macosx backend (or even 100% if it is possible), but when I think embedded, I generally think more of actually displaying as a panel inside of another app, rather than opening a new window with default behavior. We have several examples of this in our docs (just not with macos, and assuming that you are writing the app in python): https://matplotlib.org/stable/gallery/user_interfaces/index.html In these cases generally we do not use the pyplot interface (at all, not even for These objects are defined in objective C code for the macos backend, but I'm not totally clear on how you would instantiate them and use them from objective C code. (we do not provide header files or anticipate you using the objC api directly..., so I think it would have to come through python objects, and not sure how that would work) |
The actual app that this behavior manifested itself, is a large C++ /
Obj-C++ application, that added embedding Python as a scripting language to
let customers write Python scripts in a Scintilla based editor window.
Allowing them to write arbitrary Python scripts, as well as import from our
C++ based internal built-in extension package giving access to data
structures and some application interfaces from Python. And then run those
scripts from the embedded Python.
The app is not written in Python, just user written scripts. They can use
pip to add arbitrary packages to the isolated environment. But since
Python is linked in and supplied as an embedded Python framework, it opens
up potential issue of crashes from imported packages. ( the sample apps I
presented, just use the installed Python, but still link and load Python
into the apps address space). I will look at your samples, see if there is
a way to massage into a workaround, but the main application event loop is
Cocoa not Python. As I mentioned earlier my current work around is to
force the AGG backend if matplotlib can be imported, but that prevent users
from utiilizing a lot of functionality. I can get a little more slick by
checking for presence of PyQt, import that, and forcing PyAgg just in case
the user does an import matplotlib in their code.
Paul
…On Fri, Oct 20, 2023 at 6:50 PM Kyle Sunden ***@***.***> wrote:
When I run when the app first opens I get:
ERROR: Setting <View: 0x13f87c990> as the first responder for window <Window: 0x117ad81c0>, but it is in a different window ()! This would eventually crash when the view is freed. The first responder will be set to nil.
(Along with what appears to be a stack trace)
We have this message here:
https://github.com/matplotlib/matplotlib/blob/fcd5bb1a2b065e30acc530cb3e4a77fb99aea447/src/_macosx.m#L529-L530
I am able to make that warning go away by swapping the order of those two
lines (so that the view is attached to the window *before* it is set as
the first responder.
However, that does not actually change any behavior.
I am also seeing two more errors:
Unable to open mach-O at path: default.metallib Error:2
No error handler for XPC error: Connection invalid
The first shows up when the window opens, the second when it closes.
Neither matplotlib, nor the example app appear to make any reference to
metallib, so not sure where that is being triggered.
Some quick searching seems to indicate that the second is most often noise
and not a real problem.
Neither show up in the qtagg case.
Now, I honestly don't know how to do it with the macosx backend (or even
100% *if* it is possible), but when I think embedded, I generally think
more of actually displaying as a panel inside of another app, rather than
opening a new window with default behavior. We have several examples of
this in our docs (just not with macos, and assuming that you are writing
the app in python):
https://matplotlib.org/stable/gallery/user_interfaces/index.html
In these cases generally we do not use the pyplot interface (at all, not
even for plt.subplots) and adding the canvas and toolbar directly into
the gui framework's layout system.
These objects *are* defined in objective C code for the macos backend,
but I'm not totally clear on how you would instantiate them and use them
from objective C code. (we do not provide header files or anticipate you
using the objC api directly..., so I think it would have to come through
python objects, and not sure how that would work)
—
Reply to this email directly, view it on GitHub
<#27147 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAOTME4SS36SATHTSHSDLR3YAL5ZVAVCNFSM6AAAAAA6HJGIOSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONZTGQ4DEMBSHA>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
When you say "PyAgg", do you mean "qtagg"?, there is no such backend called "PyAgg". If you control the installed packages, I suppose you could include qt bindings... though that does seem a little silly to bundle Qt in a non-Qt app... (plus licensing when shipping Qt gets more complicated, I'll leave it at that, I am not a lawyer). I did also try
And |
Yes, I meant QtAgg, and because we let users install their own packages
into the isolated environment, I don’t control packages. We bundle a
complete Python within our app bundle inclusing the pip tooling. But bundle
only the Python, which our lawyers gave give blessing.
…On Fri, Oct 20, 2023 at 8:58 PM Kyle Sunden ***@***.***> wrote:
When you say "PyAgg", do you mean "qtagg"?, there is no such backend
called "PyAgg".
If you control the installed packages, I suppose you *could* include qt
bindings... though that does seem a little silly to bundle Qt in a non-Qt
app... (plus licensing when shipping Qt gets more complicated, I'll leave
it at that, I am not a lawyer).
I did also try tkagg, as tk is (often, though technically optional)
included in base Python installs, but that doesn't even show the plot in
the first place and just exits as:
[NSApplication macOSVersion]: unrecognized selector sent to instance 0x12f7291c0
And webagg does kind of work as well, at least it opens in the browser,
but there is no way of closing the webserver and the application window is
just frozen with the spinning beachball of death. So not ideal, but may
have places to push on to make the experience better (e.g. running in a
background thread may unlock the UI, then maybe could be some way to tell
that the user provided script is still running and signal it to stop)
—
Reply to this email directly, view it on GitHub
<#27147 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAOTME4RES7NCYHMVNQYVNTYAMMZ7AVCNFSM6AAAAAA6HJGIOSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTONZTGU3TEOBXGQ>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Took a brief look at this following discussions in #28981. The simple act of using the suggested line in We do not want to hold up the 3.10 release further at this time, so just documenting that I tried it to help with future looking at this. |
Bug summary
On macOS, default backend (Cocoa?), with Python embedded into an application, closing the last open Matplotlib window causes an uncatchable exit. It does not throw a system exit exception to call Python's system exit, but rather a C level exit which causes the entire application to close. This is fine if you are running Matplotlib from an interactive console, it is not fine when Python is embedded as a scripting language within an application.
Code for reproduction
Actual outcome
Application shutdown that is not catchable.
Expected outcome
Window closes and script stops running and control is returned to interpreter, but Application with Python interpreter continues running. Backend returns to a state waiting for another plot / window to be opened.
Additional information
Use Matplotlib from an application that embeds Python as a scripting language. Close last Matplotlib window. Matplotlib forces application to close ungracefully, no way to catch close, no way to save / close opened files no way for an orderly shutdown and a C level exit is called.
Matplotlib always forces exit for every version tried.
Why: A call to exit() or exit_() at the C level of the code, not a Python SystemExit.
Fix: Don't terminate the application with an uncatchable exit.
Operating system
macOS
Matplotlib Version
3.8.0 and prior
Matplotlib Backend
MacOSX
Python version
3.11.5 ( and earlier all the way back to 3.5)
Jupyter version
No response
Installation
pip
The text was updated successfully, but these errors were encountered: