Uploaded image for project: 'Qt for Python'
  1. Qt for Python
  2. PYSIDE-1495

QUiLoader registered custom widget classes not being garbage collected

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P2: Important
    • None
    • 5.15.2
    • PySide
    • None
    • Python 3.8.2
    • macOS

    Description

      Hi,

      I have recently started experimenting with QUiLoader. I understand why it's better in the long run to use pyside2-uic, but I was playing with alternatives.

      I noticed that if I register a custom widget class referenced in a .ui file, that the instance generated from QUiLoader.load isn't garbage collected at all. I compare this with the behaviour of widgets entirely created in Python code which are garbage collected.

      The above behaviour isn't a problem until you have Python objects as instance attributes in those classes that need cleaning up (multiprocessing objects are what I ultimately have in mind). Because there is no garbage collection on the widgets, these too are never collected.

      My initial suspicion was that the QUiLoader instance was keeping a reference to the generated widgets, but even del'ing that doesn't GC the widgets loaded. So I'm stumped.

      I've put my reproducible into a gist: https://gist.github.com/foundry-markf/c2552b32f67720cf7f925d71a33e2186

      Run the python script (tested in Python 3.8.2 against PySide2 5.15.2 - I've not tried regressing PySide2 versions), and it will open a main window with two buttons showing; one to create a QDialog from code, the other from a .ui file. Both share a Python code class, which is registered with the QUiLoader in the latter case. There is logging that it output to the console to show what is happening. Closing the dialogs generates more logging.

      On my machine, this is the output from pressing the code dialog button and subsequently closing the dialog:

      CRITICAL:root:PySide2 version: 5.15.2
      CRITICAL:root:Opening dialog from code
      CRITICAL:root:External resource __init__ called
      CRITICAL:root:EmptyDialog __init__ called
      CRITICAL:root:EmptyDialog Qt object destroyed CRITICAL:root:SomethingWithExternalResources Qt object destroyed CRITICAL:root:Completed dialog from code
      CRITICAL:root:EmptyDialog __del__ called
      CRITICAL:root:External resource __del__ called
      

      Also on my machine, this is the output for pressing the UI dialog button and then closing it:

      CRITICAL:root:PySide2 version: 5.15.2
      CRITICAL:root:Opening dialog from UI file
      CRITICAL:root:External resource __init__ called
      CRITICAL:root:EmptyDialog __init__ called
      CRITICAL:root:EmptyDialog Qt object destroyed CRITICAL:root:SomethingWithExternalResources Qt object destroyed CRITICAL:root:Completed dialog from UI file
      

      Note the lack of two `_del_` calls at the end of the second run. This logging is from code shared between both runs of the test app.

      Is this a bug?

      Thanks

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            crmaurei Cristian Maureira-Fredes
            mark_final Mark Final
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes