如何使用Asyncio和GUI读取文件。

2022-03-25 00:00:00 python python-asyncio

问题描述

我有一个文本文件,其名称用逗号解析,如下所示:

Ann Marie,Smith,ams@companyname.com

列表中可能有100多个名字。我省略了生成所有其他GUI组件的代码,将重点放在加载组合框和项上。

问题:

如何实现asyncio在不阻塞主线程加载其他GUI组件的情况下读取文本文件。

这是我能想到的最好的了:

import wx
import asyncio


class Mywin(wx.Frame):

    def __init__(self, parent, title):
        super(Mywin, self).__init__(parent, title=title, size=(300, 200))


        self.panel = wx.Panel(self)
        box = wx.BoxSizer(wx.VERTICAL)
        self.eventloop()

        box.Add(self.combo, 1, wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5)
        box.AddStretchSpacer()

        self.panel.SetSizer(box)
        self.Centre()
        self.Show()

        #code to display and position GUI components left out


    async def readlist(self):
        filename = 'employees.txt'
        empList = []
        with open(filename) as f_obj:
            for line in f_obj:
                empList.append(line)
        return empList

    async def managecombobox(self, loop):
        task = loop.create_task(self.readlist())
        return_value = await task
        self.combo = wx.ComboBox(self.panel, choices=return_value)

    def eventloop(self):
        event_loop = asyncio.get_event_loop()
        try:
            event_loop.run_until_complete(self.managecombobox(event_loop))
        finally:
            event_loop.close()

    def OnCombo(self, event):
        self.label.SetLabel("You selected" + self.combo.GetValue() + " from Combobox")


app = wx.App()
Mywin(None, 'ComboBox Demo')
app.MainLoop() 

解决方案

此函数

async def readlist(self):
    filename = 'employees.txt'
    empList = []
    with open(filename) as f_obj:
        for line in f_obj:
            empList.append(line)
    return empList

不是异步的。文件读取是同步的,在此期间不能运行任何其他任务。现在,由于默认情况下文件读取是阻塞的,要使其异步并非易事。一种方法是将任务提交到单独的线程:

import asyncio
from concurrent.futures import ThreadPoolExecutor

FileIOPool = ThreadPoolExecutor(8)  # you may pass here something like 2*CPU_CORES

class Mywin(wx.Frame):
    ...
    def read_file(self):
        filename = 'employees.txt'
        empList = []
        with open(filename) as f_obj:
            for line in f_obj:
                empList.append(line)
        return empList

    async def readlist(self):
        loop = asyncio.get_event_loop()
        return await loop.run_in_executor(FileIOPool, self.read_file)
现在readlist是真正异步的,在读取文件时可以运行其他操作。当您要将某些阻塞任务应用到异步框架时,这是一个标准过程。

相关文章