如何使用 Python Requests 发送 POST JSON 请求 (2026)
使用 Python requests 库发送 JSON 数据的完整指南
开始使用 Hypereal 构建
通过单个 API 访问 Kling、Flux、Sora、Veo 等。免费积分开始,扩展到数百万。
无需信用卡 • 10万+ 开发者 • 企业级服务
如何在 Python 中使用 Requests 发送 POST JSON 请求 (2026)
Python 的 requests 库是 Python 生态系统中最受欢迎的 HTTP 库,通过 JSON 数据发送 POST 请求是其最常见的用例之一。无论你是调用 REST API、向 Webhook 发送数据,还是与第三方服务集成,都需要了解构建请求的正确方法。
本指南涵盖了从基础知识到高级模式的所有内容,包括身份验证、错误处理、重试机制和异步请求。
基础知识:发送 JSON POST 请求
方法 1:使用 `json` 参数(推荐)
发送 JSON 数据最简单且最正确的方法:
import requests
url = "https://api.example.com/v1/users"
data = {
"name": "Jane Doe",
"email": "jane@example.com",
"role": "developer"
}
response = requests.post(url, json=data)
print(response.status_code) # 200
print(response.json()) # 解析 JSON 响应
当你使用 json 参数时,requests 会自动执行以下操作:
- 将字典序列化为 JSON 字符串
- 将
Content-Type请求头设置为application/json - 将数据编码为 UTF-8
方法 2:配合手动序列化使用 `data` 参数
如果你需要对序列化过程进行更多控制:
import requests
import json
url = "https://api.example.com/v1/users"
data = {
"name": "Jane Doe",
"email": "jane@example.com"
}
response = requests.post(
url,
data=json.dumps(data),
headers={"Content-Type": "application/json"}
)
何时使用此方法: 仅当你需要自定义 JSON 序列化(例如,自定义日期格式或处理 Decimal 类型)时。在所有其他情况下,请使用 json=data。
关键区别:`json` vs `data`
| 参数 | 序列化方式 | Content-Type | 使用场景 |
|---|---|---|---|
json=data |
自动 (json.dumps) |
自动设置 | 标准 JSON API |
data=json.dumps(data) |
手动 | 必须手动设置 | 自定义序列化 |
data=data |
表单编码 | application/x-www-form-urlencoded |
HTML 表单、旧版 API |
常见的错误是在调用 JSON API 时使用 data=data(未使用 json.dumps)。这会发送表单编码数据而非 JSON,服务器很可能会拒绝该请求。
添加请求头 (Headers)
标准请求头
headers = {
"Content-Type": "application/json", # 使用 json= 参数时会自动设置
"Accept": "application/json",
"User-Agent": "MyApp/1.0"
}
response = requests.post(url, json=data, headers=headers)
请注意,使用 json=data 时,你不需要手动设置 Content-Type。requests 库会自动处理。不过,手动设置 Accept 和 User-Agent 是良好的编程实践。
API Key 身份验证
headers = {
"X-API-Key": "your-api-key-here",
"Accept": "application/json"
}
response = requests.post(
"https://api.example.com/v1/generate",
json={"prompt": "A sunset over mountains", "model": "flux"},
headers=headers
)
Bearer Token 身份验证
headers = {
"Authorization": "Bearer eyJhbGciOiJIUzI1NiIs...",
"Accept": "application/json"
}
response = requests.post(url, json=data, headers=headers)
Basic Authentication 身份验证
from requests.auth import HTTPBasicAuth
response = requests.post(
url,
json=data,
auth=HTTPBasicAuth("username", "password")
)
# 简写形式
response = requests.post(url, json=data, auth=("username", "password"))
处理响应
解析 JSON 响应
response = requests.post(url, json=data)
# 检查请求是否成功
if response.ok: # 状态码为 200-299 时返回 True
result = response.json()
print(result)
else:
print(f"Error: {response.status_code}")
print(response.text)
检查完整响应信息
response = requests.post(url, json=data)
print(f"Status: {response.status_code}")
print(f"Headers: {dict(response.headers)}")
print(f"Content-Type: {response.headers.get('Content-Type')}")
print(f"Response time: {response.elapsed.total_seconds()}s")
print(f"Body: {response.text}")
# 仅在 Content-Type 为 JSON 时解析 JSON
if "application/json" in response.headers.get("Content-Type", ""):
print(f"JSON: {response.json()}")
根据不同状态码进行处理
response = requests.post(url, json=data)
match response.status_code:
case 200 | 201:
result = response.json()
print(f"Success: {result}")
case 400:
print(f"Bad request: {response.json().get('error', 'Unknown')}")
case 401:
print("Unauthorized: check your API key")
case 403:
print("Forbidden: insufficient permissions")
case 404:
print("Endpoint not found: check your URL")
case 429:
retry_after = response.headers.get("Retry-After", "60")
print(f"Rate limited: retry after {retry_after} seconds")
case 500:
print("Server error: try again later")
case _:
print(f"Unexpected status: {response.status_code}")
错误处理与重试机制
基础错误处理
import requests
from requests.exceptions import (
ConnectionError,
Timeout,
HTTPError,
RequestException
)
try:
response = requests.post(
url,
json=data,
timeout=30 # 务必设置超时时间
)
response.raise_for_status() # 如果状态码是 4xx/5xx 则抛出 HTTPError
result = response.json()
except ConnectionError:
print("Failed to connect to server")
except Timeout:
print("Request timed out")
except HTTPError as e:
print(f"HTTP error: {e.response.status_code}")
except RequestException as e:
print(f"Request failed: {e}")
指数退避重试 (Exponential Backoff)
import requests
import time
def post_with_retry(url, json_data, headers=None, max_retries=3, base_delay=1):
"""发送带有指数退避重试机制的 POST 请求。"""
for attempt in range(max_retries):
try:
response = requests.post(
url,
json=json_data,
headers=headers,
timeout=30
)
# 对于 400 范围的客户端错误不重试(429 除外)
if 400 <= response.status_code < 500 and response.status_code != 429:
response.raise_for_status()
# 触发频率限制时重试
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", base_delay * (2 ** attempt)))
print(f"Rate limited. Waiting {retry_after}s...")
time.sleep(retry_after)
continue
# 触发服务器错误时重试
if response.status_code >= 500:
raise requests.exceptions.HTTPError(response=response)
return response
except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as e:
if attempt == max_retries - 1:
raise
delay = base_delay * (2 ** attempt)
print(f"Attempt {attempt + 1} failed: {e}. Retrying in {delay}s...")
time.sleep(delay)
raise Exception(f"All {max_retries} attempts failed")
# 使用示例
response = post_with_retry(
"https://api.example.com/v1/data",
json_data={"key": "value"},
headers={"X-API-Key": "your-key"}
)
使用 `requests.Session` 复用连接
当向同一台服务器发送多个请求时,请使用 Session 来复用 TCP 连接:
import requests
session = requests.Session()
session.headers.update({
"X-API-Key": "your-api-key",
"Accept": "application/json"
})
# 通过此 session 发送的所有请求都将共享相同的请求头和连接池
response1 = session.post("https://api.example.com/v1/users", json={"name": "Alice"})
response2 = session.post("https://api.example.com/v1/users", json={"name": "Bob"})
response3 = session.post("https://api.example.com/v1/users", json={"name": "Charlie"})
session.close()
Sessions 还会自动处理 Cookie、连接池和 Keep-alive。
高级模式
发送嵌套 JSON
data = {
"user": {
"name": "Jane Doe",
"address": {
"street": "123 Main St",
"city": "San Francisco",
"state": "CA"
}
},
"preferences": {
"notifications": True,
"theme": "dark",
"languages": ["en", "es", "fr"]
}
}
response = requests.post(url, json=data)
同时发送 JSON 与文件上传
你不能在同一个请求中同时使用 json= 和 files= 参数。对于需要同时接收两者的 API,请将 JSON 编码为表单字段:
import json
files = {
"image": ("photo.jpg", open("photo.jpg", "rb"), "image/jpeg"),
"metadata": (None, json.dumps({"title": "My Photo", "tags": ["nature"]}), "application/json")
}
response = requests.post(url, files=files, headers={"X-API-Key": "key"})
流式处理大型 JSON 响应
对于返回大型响应的 API:
response = requests.post(url, json=data, stream=True)
# 分块处理响应内容
for chunk in response.iter_content(chunk_size=8192):
process_chunk(chunk)
使用 httpx 进行异步请求
对于需要异步支持的应用,请使用 httpx(它拥有与 requests 兼容的 API):
import httpx
import asyncio
async def post_json_async():
async with httpx.AsyncClient() as client:
response = await client.post(
"https://api.example.com/v1/data",
json={"key": "value"},
headers={"X-API-Key": "your-key"},
timeout=30.0
)
return response.json()
# 运行异步任务
result = asyncio.run(post_json_async())
使用 asyncio 进行并行请求
import httpx
import asyncio
async def send_batch(items):
async with httpx.AsyncClient() as client:
tasks = [
client.post(
"https://api.example.com/v1/process",
json={"item": item},
headers={"X-API-Key": "your-key"}
)
for item in items
]
responses = await asyncio.gather(*tasks)
return [r.json() for r in responses]
items = ["item1", "item2", "item3", "item4", "item5"]
results = asyncio.run(send_batch(items))
常见错误与修正
| 错误 | 问题原因 | 修正方法 |
|---|---|---|
使用 data=data 代替 json=data |
发送的是表单编码数据,而非 JSON | 使用 json=data |
缺少 timeout 参数 |
请求可能无限期挂起 | 务必设置 timeout=30 |
未调用 response.raise_for_status() |
对 4xx/5xx 错误静默失败 | 添加错误检查 |
| 硬编码 API Key | 安全风险 | 使用环境变量 |
| 未使用 Session | 发送多个请求时速度较慢 | 使用 requests.Session() |
| 忽略 Content-Type 响应头 | 在非 JSON 响应上调用时会崩溃 | 调用 .json() 前先检查响应头 |
快速参考
import requests
# 简单 POST
response = requests.post("https://api.example.com/data", json={"key": "value"})
# 带有请求头
response = requests.post(url, json=data, headers={"X-API-Key": "key"})
# 带有超时
response = requests.post(url, json=data, timeout=30)
# 带有身份验证
response = requests.post(url, json=data, auth=("user", "pass"))
# 检查响应
response.status_code # 200
response.json() # 解析后的 JSON
response.text # 原始文本
response.headers # 响应头
response.ok # 200-299 时为 True
response.raise_for_status() # 4xx/5xx 时抛出异常
结论
一旦掌握了这些模式,使用 Python requests 发送 JSON POST 请求就会变得非常简单。在实际开发中,请使用 json=data 进行自动序列化,务必设置超时时间,为生产环境代码实现重试逻辑,并在向同一服务器发送多个请求时利用 Sessions。
如果你正在寻找一个实用的 API 来测试你的 Python HTTP 技能,Hypereal AI 提供了用于 AI 图像生成、视频制作和语音合成的 REST API。其端点接受标准的 JSON POST 请求并采用 API Key 身份验证——这正是实践本指南中涵盖模式的完美现实场景。
