I have a tkinter based GUI program running in Python 3.4.1. I have several threads running in the program to get JSON data from various urls. I am wanting to add some WebSocket
First, you're getting AssertionError: There is no current event loop in thread 'Thread-1'.
because asyncio
requires each thread in your program to have its own event loop, but it will only automatically create an event loop for you in the main thread. So if you call asyncio.get_event_loop
once in the main thread it will automatically create a loop object and set it as the default for you, but if you call it again in a child thread, you'll get that error. Instead, you need to explicitly create/set the event loop when the thread starts:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
Once you've done that, you should be able to use get_event_loop()
in that specific thread.
It is possible to start an asyncio
event loop in a subprocess started via multiprocessing
:
import asyncio
from multiprocessing import Process
@asyncio.coroutine
def coro():
print("hi")
def worker():
loop = asyncio.get_event_loop()
loop.run_until_complete(coro())
if __name__ == "__main__":
p = Process(target=worker)
p.start()
p.join()
Output:
hi
The only caveat is that if you start an event loop in the parent process as well as the child, you need to explicitly create/set a new event loop in the child if you're on a Unix platform (due to a bug in Python). It should work fine on Windows, or if you use the 'spawn' multiprocessing
context.
I think it should be possible to start an asyncio
event loop in a background thread (or process) of your Tkinter application and have both the tkinter
and asyncio
event loop run side-by-side. You'll only run into issues if you try to update the GUI from the background thread/process.