惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Engineering at Meta
Engineering at Meta
量子位
云风的 BLOG
云风的 BLOG
P
Proofpoint News Feed
月光博客
月光博客
A
About on SuperTechFans
博客园 - 聂微东
Spread Privacy
Spread Privacy
B
Blog
NISL@THU
NISL@THU
小众软件
小众软件
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cyber Attacks, Cyber Crime and Cyber Security
Google DeepMind News
Google DeepMind News
Last Week in AI
Last Week in AI
T
Threatpost
Stack Overflow Blog
Stack Overflow Blog
博客园 - 叶小钗
Cyberwarzone
Cyberwarzone
Scott Helme
Scott Helme
P
Privacy & Cybersecurity Law Blog
C
Cisco Blogs
Cisco Talos Blog
Cisco Talos Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
P
Palo Alto Networks Blog
C
Check Point Blog
O
OpenAI News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
IT之家
IT之家
T
Threat Research - Cisco Blogs
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Know Your Adversary
Know Your Adversary
T
The Exploit Database - CXSecurity.com
N
News and Events Feed by Topic
P
Privacy International News Feed
B
Blog RSS Feed
Google DeepMind News
Google DeepMind News
H
Heimdal Security Blog
Martin Fowler
Martin Fowler
Schneier on Security
Schneier on Security
Webroot Blog
Webroot Blog
The GitHub Blog
The GitHub Blog
V
Visual Studio Blog
V2EX - 技术
V2EX - 技术
V
Vulnerabilities – Threatpost
博客园 - 司徒正美
C
CERT Recently Published Vulnerability Notes
H
Hacker News: Front Page
PCI Perspectives
PCI Perspectives

博客园 - 一名程序媛呀

Anki插件开发必知必会:钩子函数与右键菜单定制 从卡顿到丝滑:FastAPI 调用外部 API 的正确姿势(httpx 实战) 还在 XHR、Fetch 和 Axios 之间纠结?我踩过的坑,希望你一个都不用碰到 你的REST接口还在“过度投喂”数据吗?——FastAPI + GraphQL实战避坑指南 Uvicorn、Gunicorn 傻傻分不清?FastAPI 生产部署避坑指南 Termux里的二进制和脚本,到底怎么运行才不踩坑?Termux-service 保活妙招! 刚部署的 LibreTranslate 频频翻车?我掏出了 20 年前的 StarDict 词典,用 FastAPI 搭了个本地词典翻译 API 别再用网页翻译看源码了!你的私人翻译神器LibreTranslate,部署避坑指南来了 掏出手机就能搭个 WebDAV 同步服务器?这操作有点香 别只盯着GitBook了!这个文档神器让你的笔记秒变网站 写爬虫时用了代理还被封?Python 代理的那些隐藏坑,我替你踩明白了 FastAPI 身份验证总踩坑?这份 FastAPI Users “避坑指南”请收好 旧手机别扔!用 Termux 搭个私人云盘,比网盘香多了 你的FastAPI又在服务器上“跑不起来”了?来,今天咱把打包这件事彻底聊透 写页面时别再把 Element Plus 整个搬进来啦!Vue3按需加载的坑我帮你踩平了 前端包管理咋选?我从npm叛逃到pnpm的血泪史(附避坑指南) 聊聊 fetch 使用中我踩过的那些坑和正确打开方式 FastApiAdmin 后端接口开发好了,前端管理界面怎么调用与显示? 给 FastApiAdmin 加个“会议纪要”模块,我把后端二次开发的坑踩了个遍 我用了FastApiAdmin后,连夜把踩过的坑都整理出来了 告别 Typora 后的新欢:我把所有笔记迁移到了 Obsidian 这个“第二大脑” 你的Agent API还在裸奔?从认证到沙箱,我用FastAPI搭了几道防线 让 FastAPI Agent 思考不阻塞:手把手教你实现异步任务与后台处理方案 让FastAPI Agent真正记住你:聊聊会话记忆与持久化存储的落地实践 FastAPI Agent 函数调用实战:我让 AI 学会了“自己动手查天气“ 初探:用 FastAPI 搭建你的第一个 AI Agent 接口 FastAPI 少有人提的实用技巧:把 Depends 依赖提到路由层,代码少写60% FastAPI 生产环境静态文件完全指南:从 /favicon.ico 404 到 HSTS 混合内容,一次全根治 用了loguru我才明白,Python日志还能这么写 FastAPI 后台任务:BackgroundTasks 的使用场景与注意事项 FastAPI配置管理避坑指南:从硬编码到 .env 与 pydantic_settings 类,连路由用法都给你捋清楚 FastAPI 文件上传避坑全指南:分块存盘、类型校验与安全兜底 FastAPI + Pydantic 模型终极实战手册:从能跑就行到固若金汤,这些技巧你一定用得上 FastAPI + SQLAlchemy 2.0 通用CRUD操作手册 —— 从同步到异步,一次讲透 FastAPI订单防超卖实战:从数据库锁到Saga分布式事务,这一篇给你理清了 FastAPI 生产环境避坑指南:用 Alembic 管理数据库迁移,别再手动改表结构了! FastAPI服务半夜又挂了?先别急着重启,查查你的数据库连接池“池子”是不是漏了 FastAPI数据库ORM怎么选?我肝了三个Demo后,终于不再纠结了 Vue 3 组件通信,别只会用 Props 和 Emits 了,这几个狠活儿你得看看 Vue 3 组合式 API 香是香,但从Vue2迁移时你可别像我当初一样踩进这 3 个深坑里 我用fastapi-scaff搭了个项目,两天工期缩到两小时,老板以为我开挂了 FastAPI+Vue:文件分片上传+秒传+断点续传,这坑我帮你踩平了! FastAPI自动生成的API文档太丑?我花了一晚上把它改成了客户愿意付费的样子 告别手写 API 胶水代码:FastAPI 与 Vue 的“契约自动机” OpenAPI 实战 FastAPI + Vue 前后端分离实战:我的项目结构“避坑指南” FastAPI + Celery 实战:异步任务里调用 Redis 和数据库的全解析,及生产级组织方案 FastAPI里玩转Redis和数据库的正确姿势,别让异步任务把你坑哭了! FastAPI + Celery 实战:异步任务的坑与解法,我帮你踩了一遍 FastAPI子应用挂载:别再让root_path坑你一夜 FastAPI项目半夜报警吵醒你?聊聊告警这事儿怎么搞! 别再数据线了!用FastAPI 5分钟搭个局域网文件+剪贴板神器 FastAPI单元测试实战:别等上线被喷才后悔,TestClient用对了真香! FastAPI状态共享秘籍:别再让中间件、依赖和路由“各自为政”了! FastAPI实战:WebSocket vs Socket.IO,这回真给我整明白了! 从0到1,FastAPI + PostgreSQL + Tortoise ORM 实战避坑指南 FastAPI + PostgreSQL 实战:给应用装上“缓存”和“日志”翅膀 FastAPI + PostgreSQL 实战:从入门到不踩坑,一次讲透
httpx 传参总报错?这次把 GET、POST、文件上传到响应处理的坑给你一次填平
一名程序媛呀 · 2026-07-09 · via 博客园 - 一名程序媛呀

上回咱们聊到了,在 FastAPI 里用 httpx 替代 requests 来调用外部 API,主要说了如何使用依赖项来叫用全局单例客户端,确实实现了丝滑。

但里面只有一个Get请求的实例,对于 httpx 来说,这些还远达不到玩溜它,还有“传参、解析响应等各种小毛病”,httpx 虽然长得像 requests,但在异步世界里,参数的玩法、响应的处理、大文件的传输等等,都有自己的一套规矩。

今天咱们就把 httpx 从基础请求到高阶骚操作,试着一次性全部讲透它。看完这篇,希望实现,你在任何场景下都能把参数拿捏得死死的。

🎯 本文能帮你解决什么

🔹 搞清楚 httpx 里 paramsdatajsonfiles 到底怎么用,告别乱码和 422 错误

🔹 学会自定义 Header、Cookie,搞定需要鉴权的接口

🔹 掌握文件上传、大文件流式下载的正确姿势,不再 OOM

🔹 读懂响应对象,优雅处理 JSON、文本、二进制数据

👩‍💻我是爱折腾的一名程序媛,喜欢研究全栈开发的各种实践,热爱分享踩坑后的收获与思考,也享受用代码写出各种实用小工具解决问题的快乐。

如果你也在技术这条路上向前走,关注我,愿我们能彼此陪伴,一起成为更好的自己 🌱

🗺️ 核心脉络

🔹 万物皆始于一个客户端实例

🔹 GET 请求:参数拼接的艺术

🔹 POST 四大金刚:表单、JSON、文件、原始数据

🔹 Header 与 Cookie 的正确注入方式

🔹 返回值处理:从入门到高手的飞跃

🔹 流式请求:大文件下载再也不怕

🔹 那些悄悄崩溃的细节与避坑指南

🏗️ 第一部分:万物始于客户端,但别乱来

前面咱们说过了,全局一个 AsyncClient 服用。这里再明确一下,任何请求都要从它发出。

import httpx

async with httpx.AsyncClient(base_url="https://httpbin.org", timeout=10.0as client:

    # 里面可以疯狂发请求

你会问:“不是说要全局单例吗,怎么又 async with 了?”
全局单例是在 FastAPI 里处理时,通过 lifespanDepends 管理的。

这里为了演示方便,下面的很多例子我是用的 async with 写临时上下文,
但你心里要时刻清楚:生产环境保持单例,别模仿我这种临时创建。

🔗 第二部分:GET 请求——参数别只会拼在 URL 里

最基础,也是最常用的,发送 GET 请求:

resp = await client.get("/get")

重点在于 传参怎么传。如果你还这么写:

client.get(f"/get?name=张三&age=18")   # 这要给个差评了

为什么?一是中文编码问题,二是拼接时很容易出错
正确的姿势应该是用 params 字典来处理参数对象:

params = {"name""张三""age"18}

resp = await client.get("/get", params=params)

# httpx 会自动帮你编码成 /get?name=%E5%BC%A0%E4%B8%89&age=18

而且还有个骚操作,就是你想同一个 key 传多个值?也是可以的,直接用列表:

params = {"tag": ["python""fastapi"]}

# 结果: /get?tag=python&tag=fastapi

但这里要说个容易翻车的点:
params 里如果某个key的值是 None,默认会被忽略掉。如果你想要保留空字段,可以在传参时手动转成字符串来处理。

📬 第三部分:POST 请求——四大金刚怎么选

POST 请求的请求体类型有很多种,如果选错了,可能就被下游一巴掌呼回来了。

🔹 1. 表单数据(application/x-www-form-urlencoded)

如果要模拟页面表单的提交,这时候要用 data 参数来传字典,前提是你的参数是 key-value 类型的:

data = {"username""admin""password""123456"}

resp = await client.post("/login", data=data)

🔹 2. JSON 数据(application/json)

这也是最常见的 API 交互方式,用 json 参数直接传 Python 对象,特别是参数存在复杂类型时,httpx 会自动序列化并设好 Content-Type头信息。

payload = {"user_id"1"items": ["铅笔""橡皮"]}

resp = await client.post("/order", json=payload)

🔹 3. 文件上传(multipart/form-data)

传文件是个高频需求,但也是容易踩坑的重灾区。这时候要用 files 参数,它的值可以是文件对象或元组

# 简单上传

files = {"avatar"open("photo.jpg""rb")}

resp = await client.post("/upload", files=files)

# 自定义文件名和 MIME 类型

files = {

    "report": ("2025年报.pdf"open("report.pdf""rb"), "application/pdf")

}

resp = await client.post("/upload", files=files)

这里要注意:filesdata 可以同时使用,但别和 json 混用,否则会冲突。

🔹 4. 原始二进制或纯文本

如果你是用 content 参数传入 bytesstr,httpx 会原样塞进请求体里。

raw_data = b'\x00\x01\x02'

resp = await client.post("/binary", content=raw_data)

🎩 第四部分:Header 与 Cookie,细节决定成败

如果要自定义 Header,可以直接传字典:

headers = {"X-API-Key""secret""User-Agent""MyApp/1.0"}

resp = await client.get("/data", headers=headers)

但要特别注意:通过 client.headers 设置的全局头,会和单次请求的 headers 合并,同名键单次请求的会覆盖全局的。
不得不说,这个设计还是很贴心的,自定义和默认项都能实现了。

Cookie 管理同样简单:

cookies = {"session_id""abc123"}

resp = await client.get("/dashboard", cookies=cookies)

但如果你需要持久化 Cookie(比如登录后维持会话),这时候可以用 http.CookieJar 绑定到客户端,我这里就不展开了,但你知道它有这个能力就行,需要的时候再深入研究。

📦 第五部分:返回值处理——别只看 resp.json()

拿到响应对象后,你应该根据 Content-Type 值选择合适的解析方法,可别二话不说全部 .json() 梭哈。

下面解释下常见的返回类型解析方式,以及应对哪种类型的返回值:

🔹 resp.status_code:检查状态码,好习惯是调用 resp.raise_for_status() 让 4xx/5xx 立即抛异常。

🔹 resp.text:返回解码后的字符串(默认用响应头里的编码,智能)。

🔹 resp.json():解析 JSON,返回字典或列表。如果响应体不是合法 JSON 格式,可能会爆 JSONDecodeError 错误,要小心。

🔹 resp.content:获取原始字节流,下载图片、视频等。

🔹 resp.headers:查看响应头,比如获取 Content-Type 的值等。

下面来个实战:检查状态码后再解析返回值。

resp = await client.get("/user/1")

if resp.status_code == 200:

    user = resp.json()

else:

    print(f"错误:{resp.status_code} - {resp.text}")

上面这些算是常用的功能都有了,但我想说,它的能力还不止哦!还有更优雅的流式读取,接着看。

🌊 第六部分:流式响应——大文件别想一次性吞进内存

下载大文件时,如果你直接傻傻地 content = resp.content,那几百兆或者上G的数据能直接撑爆内存。
这时候就必须用流式响应了,然后分片保存到本地文件中。

async with client.stream("GET""/bigfile.zip"as resp:

    resp.raise_for_status()

    with open("download.zip""wb"as f:

        async for chunk in resp.aiter_bytes():

            f.write(chunk)

client.stream() 返回的响应对象不会立即读取所有数据,而是通过 aiter_bytes() 逐块读取,内存占用是恒定的一片的大小,这才是工业级的优雅。

同理,流式读取文本行,可以处理大型 JSON Lines,比如:日志文件

async with client.stream("GET""/logs.txt"as resp:

    async for line in resp.aiter_lines():

        print(line)

🚨 第七部分:要特别注意的那些悄悄崩溃的细节

🔹 超时一定要设死

前面强调过,再强调一次。客户端级别设:

client = httpx.AsyncClient(timeout=10.0)  # 10秒总超时

你也可以精细控制连接、读取和写入的不同超时定义:

timeout = httpx.Timeout(5.0, connect=3.0, read=5.0, write=2.0)

🔹 代理配置不迷路

如果公司网络需要代理,那就直接传代理地址给它:

proxies = "http://proxy.com:8080"

client = httpx.AsyncClient(proxies=proxies)

🔹 重试不要靠手写

网络波动是永远不可避免的,但这时别急着手动写 try/except 循环。

httpx 可以结合 tenacity 库做自动重试,但更建议在 AsyncClienttransport 层加 httpx.HTTPTransport(retries=3),这是同步用法。
异步重试通常用中间件或依赖注入实现,这些先作个了解即可。

💬 工具用得好,下班才能早

啰嗦了这么多,核心就一句话:参数放对位置,响应按需解析,大文件走流,超时别忘设。
如果你把这些套路都刻进脑子里,那你的 FastAPI 项目就不大可能在网络调用上掉链子。

老样子,如果你觉得对你有那么一...点点收获,那就顺手点击收藏加个关注吧,以防下次再遇到 httpx 参数问题的时候找不到,也让我看到我的辛苦总结能帮到各位!
如果你还有什么踩坑经历或者不同意见,也欢迎评论区里聊聊,咱们一起学习,一起进步、成长!🎯