From ce6bcb9ff8cec13ad3fd6fa9c032e4d0dee6f73f Mon Sep 17 00:00:00 2001 From: Stephen Gruppetta Date: Mon, 7 Sep 2026 10:56:34 +0000 Subject: [PATCH 1/2] Sample code for: Python HTTPX: Making HTTP Requests With HTTPX2 --- python-httpx/README.md | 3 +++ python-httpx/async_request.py | 12 ++++++++++++ python-httpx/auth_header.py | 14 ++++++++++++++ python-httpx/closed_client_error.py | 6 ++++++ python-httpx/custom_timeouts.py | 7 +++++++ python-httpx/default_timeout_error.py | 3 +++ python-httpx/fetch_all.py | 14 ++++++++++++++ python-httpx/first_request.py | 5 +++++ python-httpx/handle_errors.py | 20 ++++++++++++++++++++ python-httpx/handle_errors_async.py | 26 ++++++++++++++++++++++++++ python-httpx/http2_client.py | 5 +++++ python-httpx/post_request.py | 9 +++++++++ python-httpx/requests_version.py | 5 +++++ python-httpx/requirements.txt | 2 ++ python-httpx/reusable_client.py | 9 +++++++++ python-httpx/stream_download.py | 9 +++++++++ python-httpx/timeout_fires.py | 9 +++++++++ 17 files changed, 158 insertions(+) create mode 100644 python-httpx/README.md create mode 100644 python-httpx/async_request.py create mode 100644 python-httpx/auth_header.py create mode 100644 python-httpx/closed_client_error.py create mode 100644 python-httpx/custom_timeouts.py create mode 100644 python-httpx/default_timeout_error.py create mode 100644 python-httpx/fetch_all.py create mode 100644 python-httpx/first_request.py create mode 100644 python-httpx/handle_errors.py create mode 100644 python-httpx/handle_errors_async.py create mode 100644 python-httpx/http2_client.py create mode 100644 python-httpx/post_request.py create mode 100644 python-httpx/requests_version.py create mode 100644 python-httpx/requirements.txt create mode 100644 python-httpx/reusable_client.py create mode 100644 python-httpx/stream_download.py create mode 100644 python-httpx/timeout_fires.py diff --git a/python-httpx/README.md b/python-httpx/README.md new file mode 100644 index 0000000000..e5acfe5064 --- /dev/null +++ b/python-httpx/README.md @@ -0,0 +1,3 @@ +# Python HTTPX: Making HTTP Requests With HTTPX2 + +This folder provides the code examples for the Real Python tutorial [Python HTTPX: Making HTTP Requests With HTTPX2](https://realpython.com/python-httpx/) diff --git a/python-httpx/async_request.py b/python-httpx/async_request.py new file mode 100644 index 0000000000..b1766010a9 --- /dev/null +++ b/python-httpx/async_request.py @@ -0,0 +1,12 @@ +import asyncio + +import httpx2 + + +async def main(): + async with httpx2.AsyncClient(base_url="https://api.github.com") as client: + response = await client.get("/events") + print(response.status_code) + + +asyncio.run(main()) diff --git a/python-httpx/auth_header.py b/python-httpx/auth_header.py new file mode 100644 index 0000000000..9b309fc26e --- /dev/null +++ b/python-httpx/auth_header.py @@ -0,0 +1,14 @@ +import httpx2 + +with httpx2.Client( + base_url="https://api.github.com", + headers={ + "Authorization": "Bearer your-token", + "Accept": "application/vnd.github+json", + }, +) as client: + first = client.get("/events") + second = client.get("/repos/python/cpython") + +print(first.status_code, second.status_code) +print(second.request.headers["Accept"]) diff --git a/python-httpx/closed_client_error.py b/python-httpx/closed_client_error.py new file mode 100644 index 0000000000..21e2f3345f --- /dev/null +++ b/python-httpx/closed_client_error.py @@ -0,0 +1,6 @@ +import httpx2 + +with httpx2.Client() as client: + pass + +client.get("https://api.github.com/events") diff --git a/python-httpx/custom_timeouts.py b/python-httpx/custom_timeouts.py new file mode 100644 index 0000000000..1fbc8d902d --- /dev/null +++ b/python-httpx/custom_timeouts.py @@ -0,0 +1,7 @@ +import httpx2 + +timeout = httpx2.Timeout(connect=5.0, read=10.0, write=None, pool=5.0) + +with httpx2.Client(timeout=timeout) as client: + response = client.get("https://api.github.com/events") + print(response.status_code) diff --git a/python-httpx/default_timeout_error.py b/python-httpx/default_timeout_error.py new file mode 100644 index 0000000000..ecbe9f2fc7 --- /dev/null +++ b/python-httpx/default_timeout_error.py @@ -0,0 +1,3 @@ +import httpx2 + +httpx2.get("https://httpbin.org/delay/6") diff --git a/python-httpx/fetch_all.py b/python-httpx/fetch_all.py new file mode 100644 index 0000000000..dd52281b24 --- /dev/null +++ b/python-httpx/fetch_all.py @@ -0,0 +1,14 @@ +import asyncio + +import httpx2 + + +async def fetch_all(paths): + async with httpx2.AsyncClient(base_url="https://api.github.com") as client: + coroutines = [client.get(path) for path in paths] + responses = await asyncio.gather(*coroutines) + return [response.status_code for response in responses] + + +paths = ["/events", "/repos/python/cpython", "/repos/psf/requests"] +print(asyncio.run(fetch_all(paths))) diff --git a/python-httpx/first_request.py b/python-httpx/first_request.py new file mode 100644 index 0000000000..975f715142 --- /dev/null +++ b/python-httpx/first_request.py @@ -0,0 +1,5 @@ +import httpx2 + +response = httpx2.get("https://api.github.com/events") +print(response.status_code) +print(response.json()) diff --git a/python-httpx/handle_errors.py b/python-httpx/handle_errors.py new file mode 100644 index 0000000000..33e7976f80 --- /dev/null +++ b/python-httpx/handle_errors.py @@ -0,0 +1,20 @@ +import httpx2 + +timeout = httpx2.Timeout(5.0) + +with httpx2.Client(timeout=timeout) as client: + try: + response = client.get("https://api.github.com/nonexistent") + response.raise_for_status() + except httpx2.ConnectTimeout: + print("Timed out while connecting to the host.") + except httpx2.ReadTimeout: + print("Timed out while receiving data from the host.") + except httpx2.WriteTimeout: + print("Timed out while sending data to the host.") + except httpx2.PoolTimeout: + print("Timed out waiting for a pool connection.") + except httpx2.HTTPStatusError as error: + print(f"Bad response: {error.response.status_code}") + except httpx2.RequestError as error: + print(f"A network problem occurred: {error}") diff --git a/python-httpx/handle_errors_async.py b/python-httpx/handle_errors_async.py new file mode 100644 index 0000000000..afc66d90d1 --- /dev/null +++ b/python-httpx/handle_errors_async.py @@ -0,0 +1,26 @@ +import asyncio + +import httpx2 + + +async def main(): + timeout = httpx2.Timeout(5.0) + async with httpx2.AsyncClient(timeout=timeout) as client: + try: + response = await client.get("https://api.github.com/nonexistent") + response.raise_for_status() + except httpx2.ConnectTimeout: + print("Timed out while connecting to the host.") + except httpx2.ReadTimeout: + print("Timed out while receiving data from the host.") + except httpx2.WriteTimeout: + print("Timed out while sending data to the host.") + except httpx2.PoolTimeout: + print("Timed out waiting for a pool connection.") + except httpx2.HTTPStatusError as error: + print(f"Bad response: {error.response.status_code}") + except httpx2.RequestError as error: + print(f"A network problem occurred: {error}") + + +asyncio.run(main()) diff --git a/python-httpx/http2_client.py b/python-httpx/http2_client.py new file mode 100644 index 0000000000..8b39a6f7f9 --- /dev/null +++ b/python-httpx/http2_client.py @@ -0,0 +1,5 @@ +import httpx2 + +with httpx2.Client(http2=True) as client: + response = client.get("https://api.github.com/events") + print(response.http_version) diff --git a/python-httpx/post_request.py b/python-httpx/post_request.py new file mode 100644 index 0000000000..dad5ee577c --- /dev/null +++ b/python-httpx/post_request.py @@ -0,0 +1,9 @@ +import httpx2 + +with httpx2.Client() as client: + response = client.post( + "https://httpbin.org/post", + json={"title": "New issue", "body": "Found a bug"}, + ) + print(response.status_code) + print(response.json()["json"]) diff --git a/python-httpx/requests_version.py b/python-httpx/requests_version.py new file mode 100644 index 0000000000..557e82b8d0 --- /dev/null +++ b/python-httpx/requests_version.py @@ -0,0 +1,5 @@ +import requests + +response = requests.get("https://api.github.com/events") +print(response.status_code) +print(response.json()) diff --git a/python-httpx/requirements.txt b/python-httpx/requirements.txt new file mode 100644 index 0000000000..cf836bf6e8 --- /dev/null +++ b/python-httpx/requirements.txt @@ -0,0 +1,2 @@ +httpx2[http2]==2.12.0 +requests==2.34.2 diff --git a/python-httpx/reusable_client.py b/python-httpx/reusable_client.py new file mode 100644 index 0000000000..a0c725c383 --- /dev/null +++ b/python-httpx/reusable_client.py @@ -0,0 +1,9 @@ +import httpx2 + +with httpx2.Client(base_url="https://api.github.com") as client: + first = client.get("/events") + second = client.get( + "/repos/python/cpython/issues", + params={"state": "open", "per_page": 5}, + ) +print(first.status_code, second.status_code) diff --git a/python-httpx/stream_download.py b/python-httpx/stream_download.py new file mode 100644 index 0000000000..42e2f271b7 --- /dev/null +++ b/python-httpx/stream_download.py @@ -0,0 +1,9 @@ +import httpx2 + +with httpx2.Client() as client: + with client.stream( + "GET", "https://httpbin.org/stream-bytes/102400" + ) as response: + print(response.headers) + for chunk in response.iter_bytes(chunk_size=1024): + print(f"Received {len(chunk)} bytes") diff --git a/python-httpx/timeout_fires.py b/python-httpx/timeout_fires.py new file mode 100644 index 0000000000..62d1668f2e --- /dev/null +++ b/python-httpx/timeout_fires.py @@ -0,0 +1,9 @@ +import httpx2 + +timeout = httpx2.Timeout(1.0) + +with httpx2.Client(timeout=timeout) as client: + try: + client.get("https://httpbin.org/delay/3") + except httpx2.ReadTimeout: + print("The request timed out.") From c1b10fc9bdd0c5aa905fc583f51c59559143b64d Mon Sep 17 00:00:00 2001 From: Stephen Gruppetta Date: Fri, 25 Sep 2026 09:09:09 +0000 Subject: [PATCH 2/2] Sync python-httpx with the updated tutorial - custom_timeouts.py: write=5.0 instead of None - timeout_fires.py: catch TimeoutException - Add timeout_fires_async.py, stream_download_async.py, slow_endpoint.py - Remove handle_errors_async.py (replaced in the tutorial) - requirements.txt: httpx2 2.13.1 Every .py file now matches the tutorial's code blocks, formatted with the repo's ruff config. Co-Authored-By: Claude Opus 5.5 (1M context) --- python-httpx/custom_timeouts.py | 2 +- python-httpx/handle_errors_async.py | 26 -------------------------- python-httpx/requirements.txt | 2 +- python-httpx/slow_endpoint.py | 7 +++++++ python-httpx/stream_download_async.py | 15 +++++++++++++++ python-httpx/timeout_fires.py | 2 +- python-httpx/timeout_fires_async.py | 15 +++++++++++++++ 7 files changed, 40 insertions(+), 29 deletions(-) delete mode 100644 python-httpx/handle_errors_async.py create mode 100644 python-httpx/slow_endpoint.py create mode 100644 python-httpx/stream_download_async.py create mode 100644 python-httpx/timeout_fires_async.py diff --git a/python-httpx/custom_timeouts.py b/python-httpx/custom_timeouts.py index 1fbc8d902d..d866a2af2e 100644 --- a/python-httpx/custom_timeouts.py +++ b/python-httpx/custom_timeouts.py @@ -1,6 +1,6 @@ import httpx2 -timeout = httpx2.Timeout(connect=5.0, read=10.0, write=None, pool=5.0) +timeout = httpx2.Timeout(connect=5.0, read=10.0, write=5.0, pool=5.0) with httpx2.Client(timeout=timeout) as client: response = client.get("https://api.github.com/events") diff --git a/python-httpx/handle_errors_async.py b/python-httpx/handle_errors_async.py deleted file mode 100644 index afc66d90d1..0000000000 --- a/python-httpx/handle_errors_async.py +++ /dev/null @@ -1,26 +0,0 @@ -import asyncio - -import httpx2 - - -async def main(): - timeout = httpx2.Timeout(5.0) - async with httpx2.AsyncClient(timeout=timeout) as client: - try: - response = await client.get("https://api.github.com/nonexistent") - response.raise_for_status() - except httpx2.ConnectTimeout: - print("Timed out while connecting to the host.") - except httpx2.ReadTimeout: - print("Timed out while receiving data from the host.") - except httpx2.WriteTimeout: - print("Timed out while sending data to the host.") - except httpx2.PoolTimeout: - print("Timed out waiting for a pool connection.") - except httpx2.HTTPStatusError as error: - print(f"Bad response: {error.response.status_code}") - except httpx2.RequestError as error: - print(f"A network problem occurred: {error}") - - -asyncio.run(main()) diff --git a/python-httpx/requirements.txt b/python-httpx/requirements.txt index cf836bf6e8..6bdc87198d 100644 --- a/python-httpx/requirements.txt +++ b/python-httpx/requirements.txt @@ -1,2 +1,2 @@ -httpx2[http2]==2.12.0 +httpx2[http2]==2.13.1 requests==2.34.2 diff --git a/python-httpx/slow_endpoint.py b/python-httpx/slow_endpoint.py new file mode 100644 index 0000000000..5eb4e59670 --- /dev/null +++ b/python-httpx/slow_endpoint.py @@ -0,0 +1,7 @@ +import httpx2 + +timeout = httpx2.Timeout(5.0, read=15.0) + +with httpx2.Client(timeout=timeout) as client: + response = client.get("https://httpbin.org/delay/6") + print(response.status_code) diff --git a/python-httpx/stream_download_async.py b/python-httpx/stream_download_async.py new file mode 100644 index 0000000000..0a68644705 --- /dev/null +++ b/python-httpx/stream_download_async.py @@ -0,0 +1,15 @@ +import asyncio + +import httpx2 + + +async def main(): + async with httpx2.AsyncClient() as client: + async with client.stream( + "GET", "https://httpbin.org/stream-bytes/102400" + ) as response: + async for chunk in response.aiter_bytes(chunk_size=1024): + print(f"Received {len(chunk)} bytes") + + +asyncio.run(main()) diff --git a/python-httpx/timeout_fires.py b/python-httpx/timeout_fires.py index 62d1668f2e..a8c34c391c 100644 --- a/python-httpx/timeout_fires.py +++ b/python-httpx/timeout_fires.py @@ -5,5 +5,5 @@ with httpx2.Client(timeout=timeout) as client: try: client.get("https://httpbin.org/delay/3") - except httpx2.ReadTimeout: + except httpx2.TimeoutException: print("The request timed out.") diff --git a/python-httpx/timeout_fires_async.py b/python-httpx/timeout_fires_async.py new file mode 100644 index 0000000000..1d838a2741 --- /dev/null +++ b/python-httpx/timeout_fires_async.py @@ -0,0 +1,15 @@ +import asyncio + +import httpx2 + + +async def main(): + timeout = httpx2.Timeout(1.0) + async with httpx2.AsyncClient(timeout=timeout) as client: + try: + await client.get("https://httpbin.org/delay/3") + except httpx2.TimeoutException: + print("The request timed out.") + + +asyncio.run(main())