gpt4 book ai didi

python - 一起使用asyncio和Tkinter(或另一个GUI库),而无需卡住GUI

转载 作者:行者123 更新时间:2023-12-04 05:16:30 25 4
gpt4 key购买 nike

我想将asynciotkinter GUI结合使用。
我是asyncio的新手,我对它的理解不是很详细。
单击第一个按钮时,此处的示例启动10个任务。该任务只是用sleep()模拟工作几秒钟。

该示例代码在Python 3.6.4rc1上运行良好。但
问题是GUI被冻结。当我按下第一个按钮并启动10个异步任务时,除非完成所有任务,否则无法在GUI中按下第二个按钮。 GUI永远不会冻结-这是我的目标。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from tkinter import *
from tkinter import messagebox
import asyncio
import random

def do_freezed():
""" Button-Event-Handler to see if a button on GUI works. """
messagebox.showinfo(message='Tkinter is reacting.')

def do_tasks():
""" Button-Event-Handler starting the asyncio part. """
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(do_urls())
finally:
loop.close()

async def one_url(url):
""" One task. """
sec = random.randint(1, 15)
await asyncio.sleep(sec)
return 'url: {}\tsec: {}'.format(url, sec)

async def do_urls():
""" Creating and starting 10 tasks. """
tasks = [
one_url(url)
for url in range(10)
]
completed, pending = await asyncio.wait(tasks)
results = [task.result() for task in completed]
print('\n'.join(results))


if __name__ == '__main__':
root = Tk()

buttonT = Button(master=root, text='Asyncio Tasks', command=do_tasks)
buttonT.pack()
buttonX = Button(master=root, text='Freezed???', command=do_freezed)
buttonX.pack()

root.mainloop()


_side问题

...是因为这个错误,我无法再次运行任务。

Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.6/tkinter/__init__.py", line 1699, in __call__
return self.func(*args)
File "./tk_simple.py", line 17, in do_tasks
loop.run_until_complete(do_urls())
File "/usr/lib/python3.6/asyncio/base_events.py", line 443, in run_until_complete
self._check_closed()
File "/usr/lib/python3.6/asyncio/base_events.py", line 357, in _check_closed
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed


多线程

谁可以成为多线程解决方案?只有两个线程-每个循环都有自己的线程?

编辑:在审查了这个问题及其答案之后,它几乎与所有GUI库有关(例如PygObject / Gtk,wxWidgets,Qt等)。

最佳答案

在对您的代码进行少许修改后,我在主线程中创建了asyncio event_loop并将其作为参数传递给asyncio线程。现在,在提取网址时,Tkinter不会冻结。

from tkinter import *
from tkinter import messagebox
import asyncio
import threading
import random

def _asyncio_thread(async_loop):
async_loop.run_until_complete(do_urls())


def do_tasks(async_loop):
""" Button-Event-Handler starting the asyncio part. """
threading.Thread(target=_asyncio_thread, args=(async_loop,)).start()


async def one_url(url):
""" One task. """
sec = random.randint(1, 8)
await asyncio.sleep(sec)
return 'url: {}\tsec: {}'.format(url, sec)

async def do_urls():
""" Creating and starting 10 tasks. """
tasks = [one_url(url) for url in range(10)]
completed, pending = await asyncio.wait(tasks)
results = [task.result() for task in completed]
print('\n'.join(results))


def do_freezed():
messagebox.showinfo(message='Tkinter is reacting.')

def main(async_loop):
root = Tk()
Button(master=root, text='Asyncio Tasks', command= lambda:do_tasks(async_loop)).pack()
buttonX = Button(master=root, text='Freezed???', command=do_freezed).pack()
root.mainloop()

if __name__ == '__main__':
async_loop = asyncio.get_event_loop()
main(async_loop)

关于python - 一起使用asyncio和Tkinter(或另一个GUI库),而无需卡住GUI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47895765/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com