tkinter MP working like a charm
Terry Reedy
tjreedy at udel.edu
Sun Dec 31 20:52:41 EST 2017
On 12/30/2017 7:57 PM, Wu Xi wrote:
> from tkinter import * # I cant see anything wrong with this , it works like a charm
This imports about 200 names. A reader may not know which names are
builtins and which are imports. There may also be accidental name
conflicts.
> from tkinter import messagebox # is there a serious concern doing things his way ?
This is the normal way to import tkinter subpackages.
> import asyncio , threading , random # goal is multi tasking with the GUI not freezing before loop completed
> # which is being achieved here !
I verified that this works in 3.7.0a3 as I believe you intend. So it is
possible to create and run a tk loop in the main thread and run async
loop (created in the main thread) in a subthread. I don't think anyone
knows when this will and will not work.
What you show below is that asyncio.sleep and asyncio.wait work under
this circumstance. Actually fetching even one url and making it
readable from the main thread, so it can be displayed in a tk Text
widget, would be even more impressive, and useful.
> def _asyncio_thread(async_loop):
> async_loop.run_until_complete(do_urls())
>
> def do_work(async_loop):
> """ Button-Event-Handler starting stuff """
> 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: {} --- sec: {}'.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_nofreeze():
> messagebox.showinfo(message='see, Tkinter is still responsive')
>
> def submain(async_loop):
> root = Tk()
> b1 = Button(master=root, text='do work', command= lambda:do_work( async_loop)).pack()
> b2 = Button(master=root, text='Frozen?', command=do_nofreeze ).pack()
.pack() returns None, and binding None to b1 and b2 is useless. Either
skip the assignment or call .pack after the assignment.
Button(master=root, text='do work',
command= lambda:do_work( async_loop)).pack()
b1 = Button(master=root, text='do work',
command= lambda:do_work( async_loop))
b1.pack()
Since b1 and b2 here are local variables not accessible output submain,
do the former. If submain were a method, 'self.b1 = Button...' would
make it easy to access the button from elsewhere, as for testing. (It
is also possible to introspect root for its contents.)
> root.mainloop()
>
> if __name__ == '__main__':
> async_loop = asyncio.get_event_loop() # all in this loop
> submain(async_loop)
To do everything in the main thread, one can replace 'root.mainloop'
with loop.run_forever (in the main thread) and repeated root.update calls.
--
Terry Jan Reedy
More information about the Python-list
mailing list