一起使用asyncio和Tkinter(或另一个GUI库),而无需冻结GUI
我想asyncio
与tkinter
GUI结合使用。我是新手asyncio
,对它的理解不是很详细。单击第一个按钮时,此处的示例启动10个任务。任务只是用a模拟工作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()
回答:
…是因为这个错误,我无法再次运行任务。
Exception in Tkinter callbackTraceback (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等)。
回答:
在对您的代码进行稍作修改后,我event_loop
在主线程中创建了asyncio并将其作为参数传递给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)
以上是 一起使用asyncio和Tkinter(或另一个GUI库),而无需冻结GUI 的全部内容, 来源链接: utcz.com/qa/402990.html