Skip to content

Memory leak when accessing magicgui as a method #732

Description

@Antyos

Describe the bug
I found this while trying to hot-reload a widget (which is probably a bad idea), but this seems like a bug regardless.

Creating an object with a @magicgui decorated method and then accessing that method via .show (even without calling) or .native will prevent the object from being garbage collected.

For example,

from magicgui import magicgui

class F:
    def __init__(self, x: int):
        self.x = x

    @magicgui()
    def func_gui(self, a: int = 1):
        print(a + self.x)

To Reproduce

# /// script
# requires-python = ">=3.13"
# dependencies = [
#     "magicgui",
#     "pyqt6==6.9.1",
# ]
#
# [tool.uv.sources]
# magicgui = { git = "https://github.com/pyapp-kit/magicgui" }
# ///
import gc

from magicgui import magic_factory, magicgui, widgets

class F(widgets.Container):
    def __init__(self, x: int):
        self.x = x
        self.func = self.func_fact()
        super().__init__()

    @magic_factory()
    def func_fact(self, a=1):
        print(a + self.x)

    @magicgui()
    def func_gui(self, a=1):
        print(a + self.x)


def count_instances(cls) -> list:
    return len([obj for obj in gc.get_objects() if isinstance(obj, cls)])


f = F(x=5)
f.func.show  # This is fine
f.func_gui.show  # [BAD] We don't have to call .show() to get the bug, just access
f.func_gui.native  # [BAD] This also breaks it

print(get_instances(F))
### 1

# f.func_gui.native.deleteLater()  # Ironically, calling this also produces the issue
# del f.func_gui  # This raises an AttributeError. Not sure if that's intended.
del f
gc.collect()

print(count_instances(F))
### 1

Expected behavior

Commenting out the f.func_gui lines will print:

1
0

Screenshots
If applicable, add screenshots to help explain your problem.

Environment (please complete the following information):

  • OS: Windows, Python 3.13.9
  • backend: PyQt6==6.9.1
  • magicgui version: from main branch

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions