I wrote code that seems to do what I want, but I'm not sure if it's a good idea since it mixes threads and event loops to run an infinite loop off the main thread. This is a minimal code snippet that captures the idea of what I'm doing:
import asyncio
import threading
msg = ""
async def infinite_loop():
global msg
while True:
msg += "x"
await asyncio.sleep(0.3)
def worker():
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
asyncio.get_event_loop().run_until_complete(infinite_loop())
t = threading.Thread(target=worker, daemon=True)
t.start()
The main idea is that I have an infinite loop manipulating a global variable each 0.3 s. I want this infinite loop to run off the main thread so I can still access the shared variable in the main thread. This is especially useful in jupyter, because if I call run_until_complete
in the main thread I can't interact with jupyter anymore. I want the main thread available to interactively access and modify msg
. Using async might seem unnecessary in my example, but I'm using a library that has async code to run a server, so it's necessary. I'm new to async and threading in python, but I remember reading / hearing somewhere that using threading with asyncio is asking for trouble... is this a bad idea? Are there any potential concurrency issues with my approach?
call_later()
instead of the loop.call_later
will execute the callback only once. A loop runs in a full-fledged coroutine that may (in a real-world example) maintain state or await other coroutines.call_later()
again. Alsoglobal
and+
on strings are considered bad practice in Python.call_later
over a simple coroutine, and there is the downside that it is harder to have a shared state. Using a coroutine for periodic execution is fairly idiomatic asyncio.