Understanding Python Coroutines and Asynchronous HTTP Requests with httpx
This article explains Python coroutines, compares them with multithreading, outlines their suitable scenarios, and demonstrates how using the httpx library for asynchronous HTTP requests can dramatically improve request performance in backend testing, backed by concrete code examples and benchmark results.
Recently, a company's Python backend project was refactored to use asynchronous coroutines, prompting the author to explore async/await syntax.
Coroutines are lightweight, user‑space threads managed by the programmer, offering a more efficient alternative to OS‑managed threads.
Compared with multithreading, coroutines give full control to the user, reduce context‑switch overhead, use much smaller stacks (≈1 KB vs 1 MB), and eliminate the need for locking mechanisms.
Coroutines are ideal for I/O‑bound, highly concurrent tasks, but unsuitable for CPU‑intensive workloads where traditional parallelism is preferable.
The httpx library extends the popular requests API with asynchronous support, making it a strong choice for high‑performance HTTP testing.
Installation is straightforward:
pip install httpx
A synchronous benchmark using httpx.get to request Baidu 200 times took about 16.6 seconds:
import asyncio import httpx import threading import time def sync_main(url, sign): response = httpx.get(url).status_code print(f'sync_main: {threading.current_thread()}: {sign}: {response}') sync_start = time.time() [sync_main(url='http://www.baidu.com', sign=i) for i in range(200)] sync_end = time.time() print(sync_end - sync_start)
The asynchronous version creates an httpx.AsyncClient and runs 200 concurrent requests, completing in roughly 4.5 seconds—a 73 % reduction in runtime:
import asyncio import httpx import threading import time client = httpx.AsyncClient() async def async_main(url, sign): response = await client.get(url) status_code = response.status_code print(f'async_main: {threading.current_thread()}: {sign}:{status_code}') loop = asyncio.get_event_loop() tasks = [async_main(url='http://www.baidu.com', sign=i) for i in range(200)] async_start = time.time() loop.run_until_complete(asyncio.wait(tasks)) async_end = time.time() loop.close() print(async_end - async_start)
These results demonstrate that asynchronous HTTP calls with coroutines can significantly speed up API testing, and mastering coroutines can elevate overall testing framework design.
Python Programming Learning Circle
A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.