Skip to content

Commit 9cf0c09

Browse files
committed
Warn if an animation is gc'd before doing anything.
Fixes #18438.
1 parent ec45ec7 commit 9cf0c09

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

lib/matplotlib/animation.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import sys
2929
from tempfile import TemporaryDirectory
3030
import uuid
31+
import warnings
3132

3233
import numpy as np
3334

@@ -907,6 +908,8 @@ class Animation:
907908
"""
908909

909910
def __init__(self, fig, event_source=None, blit=False):
911+
self._draw_was_started = False
912+
910913
self._fig = fig
911914
# Disables blitting for backends that don't support it. This
912915
# allows users to request it if available, but still have a
@@ -931,6 +934,14 @@ def __init__(self, fig, event_source=None, blit=False):
931934
if self._blit:
932935
self._setup_blit()
933936

937+
def __del__(self):
938+
if not getattr(self, '_draw_was_started', True):
939+
warnings.warn(
940+
'Animation was deleted without rendering anything. This is '
941+
'most likely unintended. To prevent deletion, assign the '
942+
'Animation to a variable that exists for as long as you need '
943+
'the Animation.')
944+
934945
def _start(self, *args):
935946
"""
936947
Starts interactive animation. Adds the draw frame command to the GUI
@@ -1166,7 +1177,7 @@ def _draw_next_frame(self, framedata, blit):
11661177
def _init_draw(self):
11671178
# Initial draw to clear the frame. Also used by the blitting code
11681179
# when a clean base is required.
1169-
pass
1180+
self._draw_was_started = True
11701181

11711182
def _pre_draw(self, framedata, blit):
11721183
# Perform any cleaning or whatnot before the drawing of the frame.
@@ -1484,6 +1495,7 @@ def __init__(self, fig, artists, *args, **kwargs):
14841495
super().__init__(fig, *args, **kwargs)
14851496

14861497
def _init_draw(self):
1498+
super()._init_draw()
14871499
# Make all the artists involved in *any* frame invisible
14881500
figs = set()
14891501
for f in self.new_frame_seq():
@@ -1695,6 +1707,7 @@ def gen():
16951707
return gen()
16961708

16971709
def _init_draw(self):
1710+
super()._init_draw()
16981711
# Initialize the drawing either using the given init_func or by
16991712
# calling the draw function with the first item of the frame sequence.
17001713
# For blitting, the init_func should return a sequence of modified

lib/matplotlib/tests/test_animation.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import gc
12
import os
23
from pathlib import Path
34
import subprocess
@@ -75,6 +76,14 @@ def test_null_movie_writer():
7576
assert writer._count == num_frames
7677

7778

79+
def test_animation_delete():
80+
anim = make_animation(frames=5)
81+
82+
with pytest.warns(Warning, match='Animation was deleted'):
83+
del anim
84+
gc.collect()
85+
86+
7887
def test_movie_writer_dpi_default():
7988
class DummyMovieWriter(animation.MovieWriter):
8089
def _run(self):

0 commit comments

Comments
 (0)