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

--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to