gpt4 book ai didi

python - 为什么 matplotlib 不能在不同的线程中绘图?

转载 作者:IT老高 更新时间:2023-10-28 20:41:33 25 4
gpt4 key购买 nike

最小工作示例

我希望下面显示一个情节,但我看不到情节并且解释器只是挂起(我的后端将自己报告为 TkAgg)。

import matplotlib.pyplot as plt
from threading import Thread

def plot():
fig, ax = plt.subplots()
ax.plot([1,2,3], [1,2,3])
plt.show()

def main():
thread = Thread(target=plot)
thread.setDaemon(True)
thread.start()
print 'Done'

如何让绘图显示?

上下文

我正在运行一个包含大量迭代的模拟,并希望每 1000 次迭代更新一次我的绘图,以便我可以监控我的模拟是如何演变的。

下面的伪代码:

iterations = 100000
for i in iterations:
result = simulate(iteration=i)
if not i % 1000:
# Update/redraw plot here:
# Add some lines, add some points, reset axis limits, change some colours

将绘图放在主线程中会导致绘图 GUI 挂起/崩溃,大概是因为我还有其他工作正在进行。所以想法是在一个单独的线程中进行绘图。

我看到了使用进程而不是线程的建议(例如 here )。但是在我的模拟运行时我无法操纵图形或轴来添加线条等,因为图形对象处于远程进程中。

编辑

我不相信这个问题与 another one 重复因为该问题涉及为什么 pyplot api 不能用于操作 两个不同的图,每个图都在一个单独的线程上。这是因为同时执行两个绘图产生的竞争条件会阻止 pyplot 确定哪个图是当前图

但是,我只有 1 个绘图,因此 pyplot 只有一个唯一的当前图形

最佳答案

正如其他人所说,Matplotlib is not thread safe ,你有一个选择是使用多处理。您说这对您不利,因为您需要访问来自不同进程的轴,但是您可以通过在模拟进程和根进程之间共享 数据 然后管理所有绘图来克服这个问题根进程中的相关事件。例如

import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
import multiprocessing
import time
import random
from Tkinter import *


#Create a window
window=Tk()



def main():
#Create a queue to share data between process
q = multiprocessing.Queue()

#Create and start the simulation process
simulate=multiprocessing.Process(None,simulation,args=(q,))
simulate.start()

#Create the base plot
plot()

#Call a function to update the plot when there is new data
updateplot(q)

window.mainloop()
print 'Done'


def plot(): #Function to create the base plot, make sure to make global the lines, axes, canvas and any part that you would want to update later

global line,ax,canvas
fig = matplotlib.figure.Figure()
ax = fig.add_subplot(1,1,1)
canvas = FigureCanvasTkAgg(fig, master=window)
canvas.show()
canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
canvas._tkcanvas.pack(side=TOP, fill=BOTH, expand=1)
line, = ax.plot([1,2,3], [1,2,10])




def updateplot(q):
try: #Try to check if there is data in the queue
result=q.get_nowait()

if result !='Q':
print result
#here get crazy with the plotting, you have access to all the global variables that you defined in the plot function, and have the data that the simulation sent.
line.set_ydata([1,result,10])
ax.draw_artist(line)
canvas.draw()
window.after(500,updateplot,q)
else:
print 'done'
except:
print "empty"
window.after(500,updateplot,q)


def simulation(q):
iterations = xrange(100)
for i in iterations:
if not i % 10:
time.sleep(1)
#here send any data you want to send to the other process, can be any pickable object
q.put(random.randint(1,10))
q.put('Q')

if __name__ == '__main__':
main()

关于python - 为什么 matplotlib 不能在不同的线程中绘图?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34764535/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com