How to render Gymnasium environment inside Jupyter without external window

I’m working with Gymnasium environments in a Jupyter notebook and want the visualization to appear only within the notebook cells. Currently when I run my code, it shows the environment correctly in the notebook but also creates an unwanted popup window that displays the same animation.

Here’s what I’m currently using:

import matplotlib.pyplot as plt
import gymnasium as gym
from IPython import display
%matplotlib inline

enviroment = gym.make('Acrobot-v1')
enviroment.reset()

for step in range(30):
   plt.imshow(enviroment.render())
   display.display(plt.gcf())    
   display.clear_output(wait=True)
   enviroment.step(enviroment.action_space.sample())

enviroment.close()

The notebook displays the animation perfectly, but I keep getting an additional interactive window that I want to prevent from appearing. How can I make sure the rendering happens exclusively within the Jupyter notebook without any external windows popping up?

Try plt.switch_backend('Agg') before importing other stuff. This forces matplotlib to use a non-interactive backend that won’t create popup windows. Worked for me when I had similar issues with opencv rendering in notebooks.

The popup happens because matplotlib creates interactive figures even with the inline backend. Fix this by adding plt.ioff() at the start of your code to turn off interactive mode. Also, call plt.close() after each display to prevent figures from piling up. This works well in my experience:

import matplotlib.pyplot as plt
import gymnasium as gym
from IPython import display
%matplotlib inline

plt.ioff()  # Disable interactive mode

environment = gym.make('Acrobot-v1')
environment.reset()

for step in range(30):
    plt.figure(figsize=(6, 4))
    plt.imshow(environment.render())
    plt.axis('off')
    display.display(plt.gcf())
    plt.close()  # Close the figure
    display.clear_output(wait=True)
    environment.step(environment.action_space.sample())

environment.close()

The key is creating and closing figures in each loop instead of reusing the same figure object.

You can try fig, ax = plt.subplots() and then use fig.canvas.draw() instead of letting it display automatically. Sometimes Jupyter gets confused about backends when you’re switching rendering modes in the same session. I’ve had luck restarting the kernel and setting the render_mode parameter right away before creating any matplotlib figures. The popup issue usually happens because matplotlib’s figure manager starts in interactive mode before you can turn it off.

Set the render mode when you create the environment. Gymnasium defaults to ‘human’ mode, which opens external windows. Use ‘rgb_array’ mode instead:

import matplotlib.pyplot as plt
import gymnasium as gym
from IPython import display
%matplotlib inline

environment = gym.make('Acrobot-v1', render_mode='rgb_array')
environment.reset()

for step in range(30):
    plt.imshow(environment.render())
    display.display(plt.gcf())
    display.clear_output(wait=True)
    environment.step(environment.action_space.sample())

environment.close()

‘rgb_array’ mode gives you pixel data directly without opening windows. Much cleaner than messing with matplotlib’s interactive settings - you’re fixing the actual problem instead of working around it.