Unsolved Garbage collection warning after transition to PySide6
-
Hello, I've recently transitioned an application from PySide2 to PySide6 and most works fine as it did before, BUT: when I close the application the following warning is printed
gc:0: ResourceWarning: gc: 1 uncollectable objects at shutdown; use gc.set_debug(gc.DEBUG_UNCOLLECTABLE) to list them
. I applied the hint and this is the result:... gc:0: ResourceWarning: gc: 1 uncollectable objects at shutdown [<PySide6.QtCore.Property object at 0x000001FE00BE8730>]
After a lot digging I could trace it back to an interaction with
matplotlib
. Importing any of the qt backends will yield this issue. Funnily, it seems to be resolved in Python 3.9. I attached a minimum example below. I ran this with PySide6 6.4.0.1 and matplotlib 3.6.2 in Python 3.8.10 and 3.9.13, and the warning only appears for 3.8.So yea, I guess the simple solution would be to switch my app's minimum python version from 3.8 to 3.9 but I'm still curious why this was not an issue with PySide2 or if there is a setting for the matplotlib that I must apply.
import gc gc.set_debug(gc.DEBUG_UNCOLLECTABLE) from PySide6 import QtWidgets from matplotlib.backends import backend_qt5agg import worker class Dialog(QtWidgets.QDialog): def __init__(self): super(Dialog, self).__init__() self.resize(882, 700) self.setModal(True) if __name__ == "__main__": app = QtWidgets.QApplication() mw = Dialog() mw.show() app.exec()
-
So as a follow up, since this bug still appeared for Python 3.9 when running the "complex version", I tried to look for more error sources.
And turns out when I run my complex app like
if __name__ == "__main__": app = QtWidgets.QApplication() mw = MainWindowAssembly() mw.show() app.exec()
everything is fine.
If instead, I run it like
def run(): app = QtWidgets.QApplication() mw = MainWindowAssembly() mw.show() app.exec() if __name__ == "__main__": run()
I get the "uncollectable object" message. Curiously, as long as
mw
appeared in the "main" part all is good. For example, this works:def run(): app = QtWidgets.QApplication() mw = MainWindowAssembly() mw.show() app.exec() return mw if __name__ == "__main__": mw = run()
This reminds me of the typical Qt beginner's mistake of not assigning your Qt object to a variable once it's created (or to
self
if it's part of a class). But in this context it does not make any sense to me.I can't reproduce it with a simple example and I cannot share the complex code. The only insight I can give on
MainWindowAssembly
is that it is a subclass of(QtWidgets.QMainWindow, Ui_MainWindow, AbstractMainWindow)
whereUi_MainWindow
is code generated viapyside6-uic
andAbstractMainWindow
is an abstract class with a Qt metaclass.class AbstractQObject(type(QtCore.QObject), abc.ABCMeta): pass class AbstractMainWindow(metaclass=AbstractQObject): ...
However, I dont think it has something to do with this abstract construct since the error still occurs when I remove the inheritance from the abstract class.
-
Hi and welcome to devnet,
Do you have the same issue if you use:
def run(): app = QtWidgets.QApplication(sys.argv) mw = MainWindowAssembly() mw.show() sys.exit(app.exec()) if __name__ == "__main__": run()
?