如何使用Asyncio和GUI读取文件。
问题描述
我有一个文本文件,其名称用逗号解析,如下所示:
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
是真正异步的,在读取文件时可以运行其他操作。当您要将某些阻塞任务应用到异步框架时,这是一个标准过程。
相关文章