run_in_executor runs blocking code in a thread/process pool.
1import asyncio2from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor34# Blocking function5def blocking_read(file_path):6 with open(file_path) as f:7 return f.read()89def cpu_heavy(n):10 return sum(i * i for i in range(n))1112async def main():13 loop = asyncio.get_event_loop()1415 # Thread pool (default)16 content = await loop.run_in_executor(17 None, # Default thread pool18 blocking_read,19 "file.txt"20 )2122 # Custom thread pool23 with ThreadPoolExecutor(max_workers=4) as executor:24 content = await loop.run_in_executor(25 executor,26 blocking_read,27 "file.txt"28 )2930 # Process pool for CPU-bound31 with ProcessPoolExecutor(max_workers=4) as executor:32 result = await loop.run_in_executor(33 executor,34 cpu_heavy,35 10**736 )3738asyncio.run(main())
vs to_thread:
run_in_executor: explicit executor control.to_thread: simpler, uses default executor.Use cases: