Please destroy the QApplication singleton before creating a new QApplication instance.
-
In an embedded python interpreter running in a C++ app, Pyside widgets can only be opened once. In our app, Python39.dll is delay loaded at runtime, and we spawn each python tool in a new thread. Somehow the QApplication instance survives this thread's termination, and we see this error when we attempt to open the widget again:
[Python error] (<class 'RuntimeError'>) RuntimeError('Please destroy the QApplication singleton before creating a new QApplication instance.')
This does not work:
if not QApplication.instance(): app = QApplication(sys.argv) else: app = QApplication.instance()
I have tried all manner of brute force deletion of QApplication without luck. Ideally there would be an API call to destroy this singleton in cases like this when it is needed. Is there one already?
PyQt works fine.
Thanks!
-
-
-
So I found a bugreport describing an undocumented call that did the trick:
QApplication.shutdown()
Described here: https://bugreports.qt.io/browse/PYSIDE-1190
By calling that after the exec() returns, we are able to re-open the Dialogs again when the code is executed.
-
@jeremy_k - Yep. Tried gc.collect() and this back on the C++ side: PyGC_Collect();
The QApplication instance is remarkably persistent. I guess there are ways of setting up a Singleton that make it impossible for people to work around it? In this case, that defense system makes the entire PySide module unusable. At this point, we're about to go PyQt.
As an aside, running this PySide code slowly makes Visual Studio 2019 unresponsive, and after about 3 debug sessions, a restart is required. Not 100% sure if it's related to PySide, but there's really not a lot else going on in this code.
-
@jeremy_k said in Please destroy the QApplication singleton before creating a new QApplication instance.:
It sounds like you're well beyond the depth of my PySide experience. I've stopped at "works the same as PyQt".
Are the destroyed and aboutToQuit signals emitted?
A test program:
import sys if sys.argv[1:] == ["PyQt"]: from PyQt5.QtCore import QCoreApplication else: from PySide6.QtCore import QCoreApplication def runme(): print("creating QApplication") app = QCoreApplication([]) app.destroyed.connect(lambda: print("destroyed")) del app runme() runme()
This works with PyQt 5:
creating QApplication destroyed creating QApplication destroyed
but fails with PySide6:
creating QApplication creating QApplication Traceback (most recent call last): File "/tmp/test.py", line 15, in <module> runme() File "/tmp/test.py", line 10, in runme app = QCoreApplication([]) RuntimeError: Please destroy the QCoreApplication singleton before creating a new QCoreApplication instance.
So apparently yes, PySide6 is standing in the way of destroying the QCoreApplication.
This
appears tomay be a known issue.https://bugreports.qt.io/browse/PYSIDE-1470
https://bugreports.qt.io/browse/PYSIDE-1647 -
So I found a bugreport describing an undocumented call that did the trick:
QApplication.shutdown()
Described here: https://bugreports.qt.io/browse/PYSIDE-1190
By calling that after the exec() returns, we are able to re-open the Dialogs again when the code is executed.
-