为何FuncAnimation在函数外调用plt.show()无法显示动画?
plt.show() Position Matters for Matplotlib Animations Great question—this is a super common gotcha with matplotlib's FuncAnimation, and it all boils down to Python's garbage collection and how animations interact with matplotlib's event loop. Let's break it down step by step:
1. How FuncAnimation Works Under the Hood
When you create a FuncAnimation instance (your ani variable), it doesn't run on its own. It depends on two critical things:
- The animation object must stay in memory (so Python doesn't delete it prematurely).
- Matplotlib's event loop (started by
plt.show()) to trigger yourupdatefunction at each interval and render frames.
2. Why Position 1 Works
Inside your anim_random_points function, the ani variable lives in the function's local scope. When you call plt.show() right after defining ani, the animation object is still active in memory—Python hasn't cleaned it up yet. The event loop starts, and FuncAnimation can keep calling your update function to animate the points as expected.
3. Why Position 2 Fails
When anim_random_points finishes running, all its local variables (including ani) go out of scope. Python's garbage collector notices no other code is referencing ani, so it deletes the entire animation object. By the time you call plt.show() in Position 2, there's no animation left to run—you're just displaying a static, empty figure with no active update tasks.
Fix: Keep a Reference to the Animation Object
To make Position 2 work, you just need to preserve a reference to ani outside the function. Here's how to adjust your code:
Modified anim_random_points Function
def anim_random_points(fig, axis): x_vals = [] y_vals = [] intensity = [] iterations = 100 colors = [ [0, 0, 1, 0], [0, 0, 1, 0.5], [0, 0.2, 0.4, 1] ] cmap = LinearSegmentedColormap.from_list("", colors) scatter = axis.scatter(x_vals, y_vals, c=[], cmap=cmap, vmin=0, vmax=1) gen_values = get_new_vals() ani = matplotlib.animation.FuncAnimation(fig, update, frames=iterations, interval=50, fargs=(x_vals, y_vals, intensity, scatter, gen_values), repeat=False) return ani # Return the animation to keep it alive outside the function
Updated Main Code
if __name__ == '__main__': fig, axis = plt.subplots() axis.set_xlabel('X Axis', size = 12) axis.set_ylabel('Y Axis', size = 12) axis.axis([0,1,0,1]) ani = anim_random_points(fig, axis) # Store the animation reference here plt.show() # Now this will run the animation correctly!
By returning ani and storing it in the main scope, you prevent Python from garbage-collecting the animation before plt.show() starts the event loop.
内容的提问来源于stack exchange,提问作者IMCoins

