Matplotlib pyplot的show()在关闭后无法工作

7
我有一个类似于这样的循环
#!/usr/bin/env python
import matplotlib.pyplot as p

for i in xrange(N):
    # Create my_image here

    # Display this image
    p.figure()
    p.imshow(my_image)
    p.show()
    p.close()

当i=0时,这个程序能够正常工作。为了让程序继续运行,我需要关闭由pyplot创建的新图形。对于所有其他循环迭代(i>0),不会创建另一个新图形,也不会显示绘图,程序只是继续执行。为什么关闭一个图形会使pyplot无法像MATLAB一样打开新图形?

我期望的行为是:

  1. p.show()处停止执行
  2. 当我关闭图形时,继续执行
  3. 再次遇到p.show()时,显示新图像。
  4. 重复步骤2直到没有更多的图形需要显示

我能够为N>=2创建连续的图表。你在使用哪个IDE(如果你在使用一个)?在获取下一个图表之前,我必须手动关闭当前的图表,因此在这个例子中p.close()是无意义的。 - Paul
我使用PyCharm编写并运行脚本。我注意到这个问题似乎只在作为脚本而不是在ipython-pylab中运行时发生。 - Dat Chu
5个回答

5

可能有更好的方法来实现imshow的动画效果,但是这个方法应该能够满足需求。这是一个轻微修改过的文档中的动画示例

# For detailed comments on animation and the techniqes used here, see
# the wiki entry http://www.scipy.org/Cookbook/Matplotlib/Animations

import matplotlib
matplotlib.use('TkAgg')

import matplotlib.pyplot as plt
import matplotlib.mlab as mlab
import matplotlib.cm as cm

import sys
import numpy as np
import time

ax = plt.subplot(111)
canvas = ax.figure.canvas

delta=0.025
x=y= np.arange(-3.0, 3.0, delta)
x,y=np.meshgrid(x, y)
z1=mlab.bivariate_normal(x, y, 1.0, 1.0, 0.0, 0.0)
z2=mlab.bivariate_normal(x, y, 1.5, 0.5, 1, 1)
z=z2-z1  # difference of Gaussians

def run(z):
    fig=plt.gcf()
    for i in range(10):
        plt.imshow(z, interpolation='bilinear', cmap=cm.gray,
                  origin='lower', extent=[-3,3,-3,3])
        canvas.draw()
        plt.clf()
        z**=2

manager = plt.get_current_fig_manager()
manager.window.after(100, run, z)
plt.show()

1
你的解决方案非常适合动画。但是我想要的不是动画,我只想要一个简单的类似MATLAB的行为,可以在算法运行时查看某个图像/矩阵。 - Dat Chu
@Dat Chu:我不知道MATLAB的行为。 - unutbu
@Dat Chu:您需要在绘图显示时暂停代码执行吗? - Paul
@Dat Chu:你可以尝试在脚本中添加p.ion()来使其运行(比如在ipython -pylab中)。这将使matplotlib进入交互模式,每个matplotlib命令都会立即显示。这对于调试目的可能是可以接受的,但我认为对于“严肃”的脚本来说,这是不被赞同的做法。在这种情况下,建议使用图形管理器,就像上面展示的那样。 - unutbu

3

可能是由于之前版本的 matplotlib 中存在 bug 导致的。当我连续发出 show() 命令时,我遇到了类似的问题——只有第一个命令会显示(并保留);但是,当我将 matplotlib 更新到 1.0.1 版本后,问题就解决了。


我升级了Matplotlib SVN,问题就解决了。我猜这是一个bug。 - Dat Chu
2
这是1.0.1版本的“新功能”:长期以来的一个请求是支持多次调用show()。这很困难,因为在操作系统、用户界面工具包和版本之间很难获得一致的行为。Eric Firing在统一后端上做了很多工作,期望的行为是使show引发所有新创建的图形并阻止执行,直到它们关闭。自上次调用以来,重复调用show应该引发新创建的图形... - wim

0
在尝试了unutbu的示例后,我发现了一种行为,可以使用PyDev进行正常调试,并逐步查看绘图。
import time, threading
import numpy
from matplotlib.pyplot import *

x = numpy.linspace(0, 10)
y = x**2

def main():
    plot(x, x)
    draw()
    time.sleep(2)
    plot(x, y)
    draw()

thread = threading.Thread()
thread.run = main

manager = get_current_fig_manager()
manager.window.after(100, thread.start)
figure(1)
show()

请注意,如果您有多个图形,请在显示()图形窗口之前“预分配”它们。否则,任何新的图形窗口似乎都被限制在调用线程中。 - eacousineau

0

我长期以来一直在研究这个问题,虽然我还没有彻底测试过,但我可能有一个解决方案。

关键在于编写更像MatLab的代码,给你的图命名,然后调用show()函数。

例如:

 from matplotlib import pyplot as plt

 fig1 = plt.figure()
 fig2 = plt.figure()

 fig1.show()
 fig2.show()

这可能适用于不同阶段的动画和绘图


0

只设置

import matplotlib.pyplot as plt

如果你设置为例子:

import matplotlib
matplotlib.use('Agg')

这是在整个应用程序上进行交互。 而且在我的情况下,这会引起 问题


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接