【问题标题】:How do I use Asyncio and GUI to read a file.如何使用 Asyncio 和 GUI 读取文件。
【发布时间】:2017-11-08 15:57:49
【问题描述】:

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

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() 

【问题讨论】:

  • 常规文件不支持异步操作。这在某种程度上是依赖于操作系统的声明,但对于 posix AFAIK 来说至少它是正确的。但是,您可以通过 ThreadPoolExecutor 将读取任务推送到单独的线程来模拟这一点。
  • @freakish - 但读取有效。它加载了组合框,我只是想知道我是否做得正确。
  • 好吧,你说的是to read the text file without blocking the main thread。您的代码正是这样做的:它阻塞主线程,直到读取整个文件。除此之外,它很好。
  • ThreadPoolExecutor 不会阻塞主线程,对吗?代码有什么问题,为什么 async 会阻塞主线程?
  • 请注意,这用于始终阻塞的文件读取。这是一个限制。有空我再给你一些代码示例。

标签: python python-asyncio


【解决方案1】:

这个函数

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 是真正异步的,其他操作可以在读取文件时运行。当您想将一些阻塞任务应用到异步框架时,这是一个标准过程。

【讨论】:

  • 感谢您的帮助。只是出于好奇,您是如何学习线程/异步的?教科书、教程、学校?
  • 我不需要event_loop.run_until_complete(readlist)
  • @S.R.你肯定需要它(不一定在课堂上)。我刚刚实施了相关部分。我通过谷歌、文档和“边做边学”学习了 asyncio。
  • 如果我必须使用event_loop.run_until_complete(readlist),这是否意味着我会阻塞直到该线程完成?
  • 我向question 询问了有关异步和期货的问题,但没有人回答,您能帮忙吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-20
相关资源
最近更新 更多