简体   繁体   中英

jupyter notebook - matplotlib shows figure even without calling plt.show()

The following is a simplified example of my code. The idea behind this class is to show the figure only when the show method is executed.

# my_module.py
import matplotlib.pyplot as plt
import numpy as np

class Test:
    def __init__(self):
        self._fig = plt.figure()
        self.ax = self._fig.add_subplot(1, 1, 1)

    def show(self):
        x = np.linspace(0, 10, 100)
        y = np.sin(x)
        self.ax.plot(x, y)
        self._fig.tight_layout()
        self._fig.show()

The code works as expected when it is executed from a Python shell or ipython. However, if I run this inside a Jypter Notebook:

from my_module import Test
t = Test()

At this point, an empty figure is visualized on the screen. I don't want that, Now, I tried to insert plt.close(self._fig) inside __init__ , but then when I run t.show() I get UserWarning: Matplotlib is currently using module://matplotlib_inline.backend_inline, which is a non-GUI backend, so cannot show the figure.

I also tried to load %matplotlib widget with the previous edit plt.close(self._fig) . The pictures is only shown when show is called, but it is just a picture with no interactive frame.

Another option would be to rewrite the class in such a way that the figure is created inside the show method. This is far from optimal as I would need to re-adjust my tests.

Are there any other ways to get it working correctly on all shells?

In the original post I've done two mistakes.

First, the figure was instantiated into the __init__ method, then the show method was called. In an interactive environment, once the figure is created it will be shown on the screen. We could turn off that behaviour with plt.ioff() , but then two things can happen:

  1. If %matplotlib widget was executed, the figure will show up only once when calling t.show() .
  2. Otherwise, no plot will be shown on the screen when calling t.show() .

Hence, plt.ioff() is not a valid solution. Instead, the figure must be instantiated when t.show() is executed.

The second mistake I did was to use self._fig.show() . Remember, in a interactive environment the figure is shown as soon as it is instantiated. Then, the previous command shows the figure a second time, Instead, I have to use plt.show() , which only display the figure once.

Here is the correct code example:

import matplotlib.pyplot as plt
import numpy as np

class Test:
    def __init__(self):
        # init some attributes
        pass

    def show(self):
        self._fig = plt.figure()
        self.ax = self._fig.add_subplot(1, 1, 1)
        x = np.linspace(0, 10, 100)
        y = np.sin(x)
        self.ax.plot(x, y)
        self._fig.tight_layout()
        plt.show()

t = Test()  # no figure is shown
t.show()    # figure is shown

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM