Skip to content

Instantly share code, notes, and snippets.

@lars-tiede
Last active April 3, 2024 15:28
Show Gist options
  • Star 73 You must be signed in to star a gist
  • Fork 21 You must be signed in to fork a gist
  • Save lars-tiede/01e5f5a551f29a5f300e to your computer and use it in GitHub Desktop.
Save lars-tiede/01e5f5a551f29a5f300e to your computer and use it in GitHub Desktop.
asyncio + multithreading: one asyncio event loop per thread
import asyncio
import threading
import random
def thr(i):
# we need to create a new loop for the thread, and set it as the 'default'
# loop that will be returned by calls to asyncio.get_event_loop() from this
# thread.
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(do_stuff(i))
loop.close()
async def do_stuff(i):
await asyncio.sleep(random.uniform(0.1, 0.5)) # NOTE if we hadn't called
# asyncio.set_event_loop() earlier, we would have to pass an event
# loop to this function explicitly.
print(i)
def main():
num_threads = 10
threads = [ threading.Thread(target = thr, args=(i,)) for i in range(num_threads) ]
[ t.start() for t in threads ]
[ t.join() for t in threads ]
print("bye")
if __name__ == "__main__":
main()
@jabarragann
Copy link

Thank you so much for this snippet of code. It was really helpful for the application I am building

@QGB
Copy link

QGB commented Nov 20, 2019

Thank you so much for this snippet of code. It was really helpful for the application I am building

"asyncio.get_event_loop" multithread

@jayzhou215
Copy link

Thanks for sharing. I try use thread pool and handle function result

import asyncio
import random
from concurrent.futures import ThreadPoolExecutor, as_completed


def thr(i):
    # we need to create a new loop for the thread, and set it as the 'default'
    # loop that will be returned by calls to asyncio.get_event_loop() from this
    # thread.
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)

    ret = loop.run_until_complete(do_stuff(i))
    loop.close()
    return ret


async def do_stuff(i):
    ran = random.uniform(0.1, 0.5)
    await asyncio.sleep(ran)  # NOTE if we hadn't called
    # asyncio.set_event_loop() earlier, we would have to pass an event
    # loop to this function explicitly.
    print(i, ran)
    return ran


def main():
    num_threads = 10
    with ThreadPoolExecutor(num_threads) as executor:
        futures = {}
        for i in range(num_threads):
            future = executor.submit(thr, i)
            futures[future] = i
        for future in as_completed(futures):
            ret = future.result()
            print(ret, futures[future])


if __name__ == "__main__":
    main()

@scherroman
Copy link

Thank you.

@dwcarr
Copy link

dwcarr commented Mar 10, 2021

Thank you. I was just about to write something like this to debug a problem, but this helped me find it instantly.

@aviallon
Copy link

You are a GENIUS, and saved me HOURS of struggle. THANK YOU.
Do you have any donation link? Because I want to tip you a coffee.

@Crazzy626
Copy link

Thank you! That exactly what I had been looking for - simple and clean and it works perfectly.

@jayzhou215 Credits for you too, your code I also tested and it does what it should,

Good luck all!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment