Python 2.7和3.6中的多个交互式Matplotlib表现不同。

3
我有一个Python脚本,它会不断循环并等待用户输入,以使其从文件中获取数据并使用Matplotlib绘制出来。我的目的是,当脚本在控制台上继续询问下一轮用户输入和绘图时,图形能够显示并保持交互状态。因此,最终用户可能会打开几个可操作的绘图窗口。
实际上,我已经在我的Python 2.7 Anaconda版本中运行了该脚本,并使用以下示例代码进行了测试(每次循环只绘制随机数据集)。
import sys
import matplotlib.pyplot as plt
import matplotlib
import numpy as np

print('matplotlib version: '+matplotlib.__version__)
version = sys.version_info[0]

def plot_data(data):
    fig = plt.figure(figsize=(6,6))
    plt.plot(data)
    plt.ion()
    plt.show()
    plt.pause(0.001)

while True:
    if version < 3:
        option = raw_input('type (1) to plot next data, (q) to quit\n')
    else:
        option = input('type (1) to plot next data, (q) to quit\n')
    if option == '1':
        data = np.random.choice(1000,100, replace = False)
        plot_data(data)
    elif option == 'q':
        break

在我的Python 3.6版本中运行代码时,图表会显示出来,但是处于非响应状态,直到我返回控制台并键入“q”退出用户输入循环。在Python 2.7中,图表窗口通过多个输入循环和绘图调用完全可用。因此,我希望有人知道这里的区别。我打印了matplotlib版本,并且似乎我的2.7和3.6环境都使用相同的matplotlib 2.0.2,所以也许是GUI处理程序的问题?


我猜你会受益于提供一个 [mcve],让人们可以测试这个程序的问题。同时,清楚地说明正在使用的 matplotlib 版本以及如何运行此脚本。 - ImportanceOfBeingErnest
好的,我更新了我的问题,并附上了能够模拟我的问题的可工作代码。 - nanogoats
'anaconda' 在导入 matplolib 方面是否会有任何更改?您能否在 python 3 中运行 'anaconda'? - tglaria
我的 Python 版本构建都是 Anaconda。我可以通过选择位于每个版本构建文件夹中的 python.exe 文件,在任一版本上运行上述 .py 文件。 - nanogoats
更正一下,我可以在Python 2中正确运行绘图,但在Python 3中却不行。(无法编辑上一条评论) - tglaria
显示剩余2条评论
1个回答

1
我不确定使用while循环和plt.ion()的设置是否有效。至少对于我来说,使用python 2.7和matplotlib 2.1并不起作用。
我认为这是可以预料的,因为只要等待用户输入,应用程序就会冻结并变得无响应。

无论如何,由于在控制台和GUI应用程序中混合使用总是有点微妙,我选择完全在GUI的事件循环中工作。

您可以将"key_press_event"连接到"1""q"键,并在打开的matplotlib窗口中显示新数据。

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=(6,6))
ax = plt.subplot(111)

def plot_data(ax, data):
    ax.clear()
    ax.plot(data)
    ax.figure.canvas.draw_idle()

def press(event=None):
    if event:
        if event.key == "1":
            data = np.random.choice(1000,100, replace = False)
            plot_data(ax, data)
        elif event.key == "q":
            plt.close()

cid= fig.canvas.mpl_connect("key_press_event", press)
plt.show()

如果您想创建多个图形,可以这样做:
import matplotlib.pyplot as plt
import numpy as np

def create_figure(data):
    fig, ax = plt.subplots(figsize=(6,6))
    ax.plot(data)
    cid = fig.canvas.mpl_connect("key_press_event", press)
    fig.show()

def plot_data():
    data = np.random.choice(1000,100, replace = False)
    create_figure(data)

def press(event=None):
    if event:
        if event.key == "1":
            plot_data()
        elif event.key == "q":
            plt.close("all")
    else:
        plot_data()

press()
plt.show()

对于更复杂的输入,您可以创建一个小GUI,收集输入并调用绘图函数。例如,可以使用Tkinter实现此目的。

from Tkinter import * # use from tkinter import *  if using python3
import matplotlib.pyplot as plt
import numpy as np

def create_figure(data):
    fig, ax = plt.subplots(figsize=(6,6))
    ax.plot(data)
    fig.show()

def plot_data(n, amp):
    try:
        n = int(n)
        amp = float(amp)
        data = amp*np.random.rand(n)
        create_figure(data)
    except:
        pass

def closeall():
    for i in plt.get_fignums():
        plt.close(i)

def create_input():
    root = Tk()
    Label(text="Number of datapoints").grid(row=1,column=0, sticky=W)
    Label(text="Amplitude").grid(row=2,column=0, sticky=W)
    tb1=Entry(root,textvariable=StringVar(root, value='24'))
    tb1.grid(row=1,column=1, sticky=W+E)
    tb2=Entry(root,textvariable=StringVar(root, value='6'))
    tb2.grid(row=2,column=1, sticky=W+E)
    b1=Button(root,text="   Plot   ",command= lambda : plot_data(tb1.get(),tb2.get()))
    b1.grid(row=4,column=1, sticky=W+E)
    b2=Button(root,text="Close All",command=closeall)
    b2.grid(row=5,column=1, sticky=W+E)
    root.mainloop()

create_input()

enter image description here


我的脚本的目标是允许多个绘图窗口同时打开并进行交互。我不想更新给定绘图窗口的数据。你能想到实现这一目标的方法吗? - nanogoats
抱歉,我没有听懂。我已经更新了答案。 - ImportanceOfBeingErnest
好的,这在3.6中确实有效,但在我的实际应用中,我需要用户在终端输入一些信息,以便程序找到并加载他们选择的下一个数据集。你能帮我将多个功能图形与同时的终端输入集成吗?谢谢。 - nanogoats
不行,正如问题所述:在我看来,终端输入会冻结绘图窗口 - 因此我不知道该怎么做。 - ImportanceOfBeingErnest
不行,因为它也在Python 2.7上为我完成了这个任务。 - ImportanceOfBeingErnest
显示剩余3条评论

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