📝 Python

run_in_executor and anyio: Sync Libraries in Async Code

P
Author
Pyland
📅
Published
30.06.2026
⏱️
Reading time
1 min
👁️
Views
107
📊
Level
Article

Sometimes you need to call a synchronous library from async code without blocking the event loop.

The problem: blocking call in async function

import asyncio, requests

async def bad_fetch(url):
    # BAD: requests.get blocks the event loop for the entire request duration
    # All other coroutines freeze and wait
    return requests.get(url).text

run_in_executor — run in thread pool

import asyncio
from concurrent.futures import ThreadPoolExecutor
import requests

executor = ThreadPoolExecutor(max_workers=10)

async def fetch_sync(url: str) -> str:
    loop = asyncio.get_running_loop()
    # requests.get runs in a separate thread, event loop is not blocked
    return await loop.run_in_executor(executor, requests.get, url)

async def main():
    results = await asyncio.gather(
        fetch_sync("https://httpbin.org/get"),
        fetch_sync("https://httpbin.org/post"),
    )

ProcessPoolExecutor — for CPU-bound tasks

from concurrent.futures import ProcessPoolExecutor

def heavy_computation(data: list) -> float:
    return sum(x ** 2 for x in data)  # CPU-intensive

async def main():
    loop = asyncio.get_running_loop()
    with ProcessPoolExecutor() as pool:
        result = await loop.run_in_executor(
            pool, heavy_computation, list(range(10_000_000))
        )
    print(result)

anyio — universal async backend

anyio works on top of asyncio or trio — same code:

import anyio

async def main():
    # to_thread.run_sync — sync code in a thread
    result = await anyio.to_thread.run_sync(blocking_function, arg1, arg2)

    # Parallel tasks via TaskGroup
    async with anyio.create_task_group() as tg:
        tg.start_soon(fetch, url1)
        tg.start_soon(fetch, url2)

# Run under asyncio or trio
anyio.run(main)

When to use what

Scenario Solution
Sync I/O library run_in_executor + ThreadPoolExecutor
CPU-intensive task run_in_executor + ProcessPoolExecutor
New async project httpx, aiosqlite instead of requests, sqlite3
Backend portability anyio

Your reaction to the article

💬 Comments (0)

🔐 Sign in to leave a comment
🚪 Login
💭

No comments yet

Be the first to share your opinion about this article!

🔗 Similar

Similar articles

Continue learning with these materials

📝

Event Loop in Python: How asyncio Achieves "Paral…

Event loop is the heart of asyncio. It doesn't run code in parallel across multiple...

📅 30.06.2026 👁️ 129
📝

pytest-django: Testing Django

Охватываемые темы: Installation, @pytest.mark.djangodb, Fixtures, Testing views.

📅 30.06.2026 👁️ 138
📝

pip: Python Package Manager

Охватываемые темы: Installing packages, Upgrading and removing, requirements.txt, Virtual environment.

📅 30.06.2026 👁️ 120

Did you like the article?

Subscribe to our updates and receive new articles first. Grow with PyLand!