asyncio

  • This library takes advantage of two new Python reserved keywords: async and await
  • await can be thought of as an asynchronous version of yield from, and has to be inside a coroutine
  • When the program reaches the await statement, the control is handed off to the event loop, which finds the next thing to run
    • this behaves very similarly to a yield in generators

Useful Functions

  • asyncio.run
  • asyncio.gather
  • asyncio.wait
  • asyncio.Queue

Useful Helper Libraries

  • aiohttp
  • aiofiles
  • aiomultiprocessing

concurrent.futures

Two patterns I’ve seen so far:

  1. Quickly toggle between multiprocessing and multithreading
with concurrent.futures.ThreadPoolExecutor as executor:
    results = executor.map(fn, iterable)
 
with concurrent.futures.ProcessPoolExecutor as executor:
    results = executor.map(fn, iterable)
  1. Schedule buffered and concurrent pipelines
with concurrent.futures.ThreadPoolExecutor() as executor:
    futures = {executor.submit(fn, val) for val in vals}
    while futures:
         done, futures = concurrent.futures.wait(
		       futures, return_when=concurrent.futures.FIRST_COMPLETED
         )
 
	       for fut in done:
               pass  # Do something
 
		   # Schedule additional tasks
         for task in more_tasks:  # `more_tasks` should be as long as `done`
              future.add(executor.submit(fn, task))

Note: This is also achievable using asyncio.wait