Skip to content

GraphicCollection.__del__ method can cause confusing tracebacks #393

@tlambert03

Description

@tlambert03

If something fails during init of a GraphicCollection, an exception will be raised, but that exception will often be hidden higher up in the stack due to a failure during cleanup in the __del__ method. for example, if you pass the wrong length of cmaps to a LineCollection:

Traceback (most recent call last):
  File "/Users/talley/dev/forks/fastplotlib/examples/desktop/line_collection/line_stack.py", line 27, in <module>
    plot.add_line_stack(data, cmap=["jet"])
  File "/Users/talley/dev/forks/fastplotlib/fastplotlib/layouts/graphic_methods_mixin.py", line 314, in add_line_stack
    return self._create_graphic(LineStack, data, z_position, thickness, colors, cmap, separation, separation_axis, name, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/talley/dev/forks/fastplotlib/fastplotlib/layouts/graphic_methods_mixin.py", line 25, in _create_graphic
    graphic = graphic_class(*args, **kwargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/talley/dev/forks/fastplotlib/fastplotlib/graphics/line_collection.py", line 547, in __init__
    super(LineStack, self).__init__(
  File "/Users/talley/dev/forks/fastplotlib/fastplotlib/graphics/line_collection.py", line 125, in __init__
    raise ValueError(
ValueError: cmap argument must be a single cmap or a list of cmaps with the same length as the data
Exception ignored in: <function GraphicCollection.__del__ at 0x1212071a0>
Traceback (most recent call last):
  File "/Users/talley/dev/forks/fastplotlib/fastplotlib/graphics/_base.py", line 477, in __del__
    super().__del__()
  File "/Users/talley/dev/forks/fastplotlib/fastplotlib/graphics/_base.py", line 171, in __del__
    del WORLD_OBJECTS[self.loc]
        ~~~~~~~~~~~~~^^^^^^^^^^
KeyError: '0x16a217250'

It would be nice to either ignore errors in the __del__ method, or do a bit more careful cleanup depending on the state of the object:

    def __del__(self):
        with contextlib.suppress(Exception):
            self.world_object.clear()
            for loc in self._graphics:
                del COLLECTION_GRAPHICS[loc]

            super().__del__()

and then you'd see:

Traceback (most recent call last):
  File "/Users/talley/dev/forks/fastplotlib/examples/desktop/line_collection/line_stack.py", line 27, in <module>
    plot.add_line_stack(data, cmap=["jet"])
  File "/Users/talley/dev/forks/fastplotlib/fastplotlib/layouts/graphic_methods_mixin.py", line 314, in add_line_stack
    return self._create_graphic(LineStack, data, z_position, thickness, colors, cmap, separation, separation_axis, name, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/talley/dev/forks/fastplotlib/fastplotlib/layouts/graphic_methods_mixin.py", line 25, in _create_graphic
    graphic = graphic_class(*args, **kwargs)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/talley/dev/forks/fastplotlib/fastplotlib/graphics/line_collection.py", line 547, in __init__
    super(LineStack, self).__init__(
  File "/Users/talley/dev/forks/fastplotlib/fastplotlib/graphics/line_collection.py", line 125, in __init__
    raise ValueError(
ValueError: cmap argument must be a single cmap or a list of cmaps with the same length as the data

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    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