Matplotlib图形挂在线程中.使用了Thread.join()



考虑以下示例

from time import sleep
import matplotlib.pyplot as plt
from threading import Thread
import numpy as np
class Monitor(Thread):
def __init__(self):
Thread.__init__(self)
_, self.ax = plt.subplots()
self.data = []
def add_point(self, pt):
self.data.append(pt)
self.ax.cla()
self.ax.plot(self.data)
plt.draw()

class Main_job(Thread):
def __init__(self, monitor):
Thread.__init__(self)
self.monitor = monitor
self.output = []
def run(self):
for i in range(20):
print(i)
pt = np.random.rand()
self.output.append(pt)
self.monitor.add_point(pt)
sleep(1)

monitor = Monitor()
monitor.start()
main = Main_job(monitor)
main.start()

我有一个执行长操作的Main_job线程,我想在运行时监视它。

I、 因此,为matplotlib图形定义了一个Thread,为我的过程定义了另一个。

代码运行良好

现在假设我想在关闭程序之前对Main_job线程的输出进行一些处理(例如打印它或将它保存到文件中(。

我在我的代码的末尾添加了以下几行

main.join()
print(main.output)

然而,这在某种程度上干扰了matplotlib,尽管根本没有修改monitor线程,但它现在挂起,直到main完成。

如何在等待main完成的同时避免monitor挂起?

EDIT 1-单线程(非工作(版本

根据FiddleStix的请求,这里是该代码的单线程版本。尽管要简单得多,但在这个版本中,图形会挂起,并且只在过程结束时显示

from time import sleep
import matplotlib.pyplot as plt
import numpy as np
_, ax = plt.subplots()
output = []
for i in range(20):
print(i)
pt = np.random.rand()
output.append(pt)
ax.cla()
ax.plot(output)
sleep(1)

绘图后添加plt.pause(0.01)可以稍微改善这种情况。然而,通过这种方式,可以显示图形,但用户只能在0.01秒内进行交互

注意:我知道用plt.pause(1)替换sleep(1)可以解决这个问题,但这里sleep只是实际代码中长时间耗时操作的代理,而不仅仅是暂停。

我认为您希望使Monitor线程成为daemon线程(文档(。如果主线程停止,守护进程线程将自动退出。通过这种方式,您可以在后台运行一些东西,而无需显式地停止第二个线程。

只需添加一个类参数即可将线程声明为守护进程:

class Monitor(Thread):
daemon = True

GUI主循环应该在主线程中运行。在单独的线程中运行作业,这样它就不会阻塞GUI。

通过在线程中使用matplotlib.pyplot.draw执行重绘,可以实现output更改时绘图的简单动画。

请考虑使用动画API对现场情节进行平滑动画。

from time import sleep
import matplotlib.pyplot as plt
from threading import Thread
import numpy as np

_, ax = plt.subplots()
output = []
class Job(Thread):
def run(self):
for i in range(10):
print(i)
pt = np.random.rand()
output.append(pt)
sleep(1)
ax.cla()
ax.plot(output)
plt.draw()
job = Job()
job.start()
plt.show()

最新更新