asyncio matplotlib show() 仍然冻结程序

Num*_*uis 5 python matplotlib python-3.x python-asyncio

我希望运行一个模拟,同时在一个 plot 中输出它的进度。我一直在查看很多线程和多处理的示例,但它们都非常复杂。所以我认为使用 Python 的新asyncio库应该会更容易。

我找到了一个例子(How to use 'yield' inside async function?)并为我的原因修改了它:

import matplotlib.pyplot as plt
import asyncio
import numpy as np


class DataAnalysis():
    def __init__(self):
        # asyncio so we can plot data and run simulation in parallel
        loop = asyncio.get_event_loop()
        try:
            loop.run_until_complete(self.plot_reward())
        finally:
            loop.run_until_complete(
                loop.shutdown_asyncgens())  # see: https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.shutdown_asyncgens
            loop.close()

    async def async_generator(self):
        for i in range(3):
            await asyncio.sleep(.4)
            yield i * i

    async def plot_reward(self):
        # Prepare the data
        x = np.linspace(0, 10, 100)

        # Plot the data
        plt.plot(x, x, label='linear')

        #plt.show()

        # add lines to plot
        async for i in self.async_generator():
            print(i)
            # Show the plot
            plt.show()


if __name__ == '__main__':
    DataAnalysis()
Run Code Online (Sandbox Code Playgroud)

我添加了一个简单的plt.show(),程序仍然冻结。我想asyncio我可以并行运行它吗?显然我的知识仍然缺乏。执行以下操作的示例将非常有帮助:

  • matplotlib每次async_generator返回一个值时,向 (of )图中添加一条线。

Num*_*uis 5

首先,我误解了 asyncio,它不会并行运行(将 asyncio 用于并行任务)。

似乎唯一对我有用的plt.pause(0.001)使用 Matplotlib 以非阻塞方式绘图)。plt.draw()打开了一个窗口,但它没有显示任何内容并plt.show冻结了程序。似乎plt.show(block=False)已弃用,使用plt.ion会导致程序完成时最终结果关闭的问题。也await asyncio.sleep(0.1)没有让情节画线。

工作代码

import matplotlib.pyplot as plt
import asyncio
import matplotlib.cbook
import warnings
warnings.filterwarnings("ignore",category=matplotlib.cbook.mplDeprecation)


class DataAnalysis():
    def __init__(self):
        # asyncio so we can plot data and run simulation in parallel
        loop = asyncio.get_event_loop()
        try:
            loop.run_until_complete(self.plot_reward())
        finally:
            loop.run_until_complete(
                loop.shutdown_asyncgens())  # see: https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.shutdown_asyncgens
            loop.close()
            # keep plot window open
            plt.show()

    async def async_generator(self):
        for i in range(3):
            await asyncio.sleep(.4)
            yield i * i

    async def plot_reward(self):
        #plt.ion()  # enable interactive mode

        # receive dicts with training results
        async for i in self.async_generator():
            print(i)
            # update plot
            if i == 0:
                plt.plot([2, 3, 4])
            elif i == 1:
                plt.plot([3, 4, 5])

            #plt.draw()
            plt.pause(0.1)
            #await asyncio.sleep(0.4)


if __name__ == '__main__':
    da = DataAnalysis()
Run Code Online (Sandbox Code Playgroud)

笔记

  • 但是,您会收到一条已弃用的消息:python3.6/site-packages/matplotlib/backend_bases.py:2445: MatplotlibDeprecationWarning: Using default event loop until function specific to this GUI is implemented warnings.warn(str, mplDeprecation),您可以使用: 抑制该消息warnings.filterwarnings()

  • 我不确定asyncio我的用例是否真的有必要......

  • 之间的差异threadingmultiprocessing对谁的兴趣:多重VS线程的Python