Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Apprendre Running Blocking Code with run_in_executor() | Advanced Control and Debugging
Python Asyncio in Depth

Running Blocking Code with run_in_executor()

Glissez pour afficher le menu

Not every library supports asyncio. requests, pandas, file system calls, and CPU-heavy functions are all blocking – calling them directly inside a coroutine freezes the entire event loop. run_in_executor() moves blocking code to a thread pool, freeing the event loop to keep running.

The Problem

Calling a blocking function inside an async context stalls all other coroutines until it returns:

123456789101112131415161718192021
import asyncio import time import nest_asyncio nest_asyncio.apply() # Blocking call inside a coroutine – freezes the event loop async def process_data(label): print(f"Starting {label}") time.sleep(1) # Blocking – no other coroutine runs during this print(f"Done {label}") async def main(): start_time = time.time() await asyncio.gather( process_data("task_A"), process_data("task_B"), ) print(f"Total time: {time.time() - start_time:.2f}s") # ~2s – sequential asyncio.run(main())

Using run_in_executor()

loop.run_in_executor(executor, func, *args) runs func in a thread pool and returns an awaitable. Pass None as the executor to use the default ThreadPoolExecutor:

123456789101112131415161718192021222324
import asyncio import time import nest_asyncio nest_asyncio.apply() # Moving a blocking call to a thread pool def blocking_process(label): print(f"Starting {label}") time.sleep(1) # Runs in a thread – event loop stays free print(f"Done {label}") async def main(): loop = asyncio.get_event_loop() start_time = time.time() await asyncio.gather( loop.run_in_executor(None, blocking_process, "task_A"), loop.run_in_executor(None, blocking_process, "task_B"), ) print(f"Total time: {time.time() - start_time:.2f}s") # ~1s – concurrent asyncio.run(main())

A Realistic Example: Mixing requests with asyncio

When you must use a synchronous HTTP library alongside async code:

1234567891011121314151617181920212223242526272829
import asyncio import requests import nest_asyncio nest_asyncio.apply() # Wrapping a blocking requests call for use in asyncio def fetch_post_sync(post_id): response = requests.get( f"https://jsonplaceholder.typicode.com/posts/{post_id}" ) return response.json()["title"] async def fetch_post_async(post_id): loop = asyncio.get_event_loop() title = await loop.run_in_executor(None, fetch_post_sync, post_id) return title async def main(): titles = await asyncio.gather( fetch_post_async(1), fetch_post_async(2), fetch_post_async(3), ) for title in titles: print(title) asyncio.run(main())

Using a Custom Executor

Pass a ThreadPoolExecutor to control the number of threads, or a ProcessPoolExecutor for CPU-bound work:

1234567891011121314151617181920212223242526
import asyncio import time from concurrent.futures import ThreadPoolExecutor import nest_asyncio nest_asyncio.apply() # Using a custom thread pool with a fixed size def heavy_computation(value): time.sleep(0.5) # Simulating CPU work return value ** 2 async def main(): loop = asyncio.get_event_loop() with ThreadPoolExecutor(max_workers=4) as executor: results = await asyncio.gather( *[ loop.run_in_executor(executor, heavy_computation, value) for value in range(1, 6) ] ) print(results) asyncio.run(main())

When to Use run_in_executor()

Use it when:

  • A third-party library does not support asyncio (e.g., requests, legacy database drivers);
  • File I/O uses standard open() instead of an async file library;
  • A CPU-bound function would block the loop for more than a few milliseconds.

Do not use it as a general workaround for writing async code – always prefer native async libraries when they exist.

question mark

What does passing None as the executor argument to run_in_executor() do?

Sélectionnez la réponse correcte

Tout était clair ?

Comment pouvons-nous l'améliorer ?

Merci pour vos commentaires !

Section 4. Chapitre 1

Demandez à l'IA

expand

Demandez à l'IA

ChatGPT

Posez n'importe quelle question ou essayez l'une des questions suggérées pour commencer notre discussion

Section 4. Chapitre 1
some-alt