Description
Bug summary
There are no leaks when we plt.show() figures and fire up the GUI mainloop. However, when we are calling savefig() without ever showing we are now creating singleshot Timers in the app, but the callback never gets triggered due to the event loop not being active/listening for these timers. This is then keeping a reference from the Timer to the Figure on every close, causing a leak when calling a bunch of savefig's.
xref: #19769
But, more specifically related to Timer's generically not firing.
identified debugging: #23059
Code for reproduction
import sys
import matplotlib.pyplot as plt
import numpy as np
import matplotlib
#matplotlib.use('agg')
data = np.random.rand(60, 60)
def plot_expr(plot_name):
plt.figure(figsize=(9, 8))
for i in range(60):
plt.plot(data[i, :])
plt.savefig(plot_name)
plt.close('all')
if __name__ == "__main__":
print(f'python: {sys.version}')
print(f'matplotlib: {matplotlib.__version__}')
print(f'backend: {matplotlib.get_backend()}')
for i in range(50):
print(f'{i}...')
plot_expr(f'leak_{i}')
Actual outcome
Timer's don't fire. You can put a log inside the callback to verify NSLog(@"Inside callback")
that the Timer gets created but doesn't trigger.
Expected outcome
Timer's should fire even if we aren't interactive.
Additional information
No response
Operating system
MacOS
Matplotlib Version
main
Matplotlib Backend
macosx
Python version
No response
Jupyter version
No response
Installation
No response