JACIN Blog

深度的 AI 应用开发者

专注 AI 应用开发、Python 后端与工程实践,持续记录大模型落地、工具构建与真实项目经验。

183篇已发布
主题索引
查看全部分类
全部文章
183
Python 开发
9 分钟

工厂基类的使用

这篇笔记聚焦一个用于 Python 本地函数管理的工具工厂基类,目标是把分散的工具函数集中注册、统一生成 OpenAI tool calling 可用的 tools 描述,并通过名称完成动态调用。示例中的 BaseTool 维护 registry 字典,使用 @BaseTool.register 类方法装饰器在函数定义阶段把函数名和函数对象写入注册表,因此 get_weather、get_time 这类函数不需要额外手工汇总。get_tools() 遍历已注册函数,借助 inspect.signature(fn) 读取参数签名,再组装出包含 type、function、description、parameters、required 等字段的 function schema,便于直接传给 OpenAI。call(name, args) 则根据工具名查找对应函数并用关键字参数执行,若名称未注册会抛出 ValueError,从而把调用入口收敛到一个方法中。文章还用“装饰器等价于 BaseTool.register(get_weather)”的展开方式解释了注册机制,帮助读者理解 registry.items() 中 name 与 fn 的来源。适合正在把 Python 函数接入 OpenAI tools、或想先掌握装饰器、注册表、函数签名提取三者协作方式的 AI 应用开发者参考。

Python 开发
15 分钟

pytest测试代码专用

这份笔记围绕 Python 项目中的 pytest 测试代码编写展开,先从 pytest 的定位、安装方式、pytest.ini 中 testpaths 与 pythonpath 的基础配置讲起,再用 tests 目录下的最小 test_example 示例说明普通函数加 assert 的测试入口。内容整理了常见测试写法,包括任意 Python 表达式断言、pytest.mark.parametrize 参数化、fixture 复用数据准备与清理逻辑、pytest.raises 捕捉异常、用 class 组织测试,以及通过文件、类、方法路径或 -k 关键字精确运行用例。命令行部分覆盖 -v、-x、--maxfail 等常用参数,适合快速建立本地测试执行习惯。后半部分转向 FastAPI 路由测试,同步接口使用 fastapi.testclient.TestClient,异步接口则结合 pytest-asyncio、httpx.AsyncClient 与 ASGITransport,在内存中直接向 ASGI app 发请求,避免启动 uvicorn 和真实端口。文章特别提示 AsyncClient(app=...) 已弃用且可能引发 502、生命周期未触发或路由异常等问题,推荐显式使用 transport=ASGITransport(app=app)。整体更像一份面向后端开发者的 pytest 与 FastAPI 接口测试速查模板,读者可以据此搭建基础测试目录、编写常见用例,并理解 ASGITransport 在异步接口测试中的作用边界。

Python 开发
10 分钟

python-格式化利器

这份笔记围绕 Python 项目的代码格式化与质量检查工具链展开,推荐用 Ruff 作为核心工具统一承担格式化、lint 和 import 排序,减少 Black、flake8、isort 分散配置带来的维护成本。配置流程从使用 uv 安装 ruff、mypy、pytest-cov、bandit、pre-commit 开始,再将 Ruff 与 mypy 配置集中写入 pyproject.toml,其中包含 100 字符行宽、自动 import 排序、自动修复,以及 SQLAlchemy 2.0 mypy 插件、未标注函数检查等类型约束。执行层面给出 ruff format、ruff check、mypy app、bandit -r app、pytest 覆盖率测试等常用命令,并说明应先 format 再 lint,以避免先看到大量可自动修复的格式报错。自动化部分覆盖 pre-commit 钩子配置、全量检查命令,以及 GitHub Actions 中在 push 和 pull_request 时运行 Ruff、mypy、bandit 的 CI 示例。文末还提供面向 FastAPI + SQLAlchemy 项目的 Makefile 模板,把 format、lint、typecheck、security、test、all 等任务封装成统一入口。适合希望快速建立本地开发、提交前检查和 CI 流程一致性的 Python 后端项目参考,尤其适用于已有 app 目录结构并使用类型检查、测试覆盖率和安全扫描的团队。

Python 开发
7 分钟

docker使用uv安装依赖

这篇笔记围绕 FastAPI 官方 Dockerfile 中用 uv 构建 Python 项目依赖的缓存优化展开,重点解释为什么同一个镜像构建流程里会出现两次 uv sync。第一次执行 uv sync --frozen --no-install-project 时,只根据 pyproject.toml 和 uv.lock 安装依赖,不安装项目源码,并借助 BuildKit 的 cache mount 与 bind mount 形成可复用的依赖层;只要锁文件和项目配置不变,修改 .py 文件就不会触发整层依赖重装。第二次 uv sync 则用于把当前项目本身安装进虚拟环境,弥补第一次跳过项目安装的结果,使源码变更只影响项目层而不是依赖层。文章还说明了 FastAPI 官方示例中没有直接 COPY 配置文件的原因:它利用 BuildKit 挂载文件参与构建,后续再通过 COPY . . 放入项目代码,从而减少无关变更对缓存的破坏。末尾给出一个基于 python:3.12-slim、uv 0.5.11、/app/.venv、PYTHONPATH=. 和 uvicorn 启动命令的 Dockerfile 雏形,可作为 FastAPI 项目镜像构建的改造参考。需要注意的是,文中示例更偏向说明依赖层缓存思路,实际项目仍应结合是否多阶段构建、是否需要第二次 uv sync 以及源码复制顺序进行调整。

Python 开发
17 分钟

定时任务(python)

这篇笔记梳理了在 Python 中实现定时任务的常见路径,适用于需要定期采集数据、固定时间发送通知、周期清理缓存或在常驻服务中触发后台逻辑的场景。内容先从 while True 加 time.sleep 的最小实现讲起,说明它无需依赖、控制直接,但会阻塞当前线程,且任务执行耗时会影响间隔,也不适合“每天几点几分”这类精确调度。随后对比 schedule 库的用法,展示 every().seconds、day.at、monday.at 等轻量语法,并解释 run_pending 加 sleep(1) 的轮询机制,强调 sleep 只是检查间隔,不等于改变任务周期。更完整的方案部分聚焦 APScheduler,说明 BlockingScheduler、BackgroundScheduler、AsyncIOScheduler 等调度器差异,以及 interval、cron、date 三类触发方式、内部任务计划表、轮询 tick、线程池执行和任务持久化能力。后半部分给出 asyncio 自定义调度示例,通过固定时间列表计算下一次运行时间,并结合 Redis 有序集合、去重 key 和 setex 过期时间实现订阅推送检查。整体结论是:脚本或一次性小任务可以用 schedule,少量异步任务且需要和 Redis 协调时可自定义 asyncio,但服务常驻、需要异步、cron、并发和更好维护性的场景更适合 APScheduler。

Python 开发
11 分钟

APScheduler解析

这篇笔记围绕 APScheduler 在 asyncio 项目中的定时任务注册方式展开,重点解释 AsyncIOScheduler 如何配合协程函数实现固定时间或固定间隔执行。示例以一个 ScheduleService 为入口,维护 08:00、12:00、18:00 三个固定时间,通过 add_job 注册 CronTrigger,并在服务启动后让 asyncio 事件循环持续运行。文中强调一个容易踩坑的点:即使使用 AsyncIOScheduler,add_job 接收的 job 仍应是普通同步可调用对象,因此需要用 wrapper 或 lambda 包装 async def,再在内部调用 asyncio.create_task 将协程提交到当前事件循环。机制部分把 APScheduler 拆成任务注册、触发器转换、调度器循环检查时间、到点执行函数几个阶段,说明 cron、interval、date 等触发条件会被保存为内部调度计划。后半部分给出常见异步写法,包括每天 10:30、每周一 9:00、每小时第 5 分钟执行,以及使用 IntervalTrigger 每 5 分钟执行一次。对于需要在 Python 异步服务中加入轻量定时任务的后端开发者,这篇内容能帮助判断协程任务应如何封装、触发器参数如何填写,以及为什么调度循环代码不需要自己手写。

Python 开发
11 分钟

装饰器的使用

这篇笔记聚焦 Python 装饰器的基本机制与进阶写法,适合已经掌握函数定义、参数传递并希望理解框架中路由、权限、缓存等语法来源的开发者。文章先把装饰器解释为“接收函数并返回新函数”的高阶函数,说明它能在不改动原函数代码的前提下加入日志、性能统计、权限校验、重试等横切逻辑,并列举了 staticmethod、classmethod、property、functools.lru_cache 等内置示例。核心部分区分了定义阶段和调用阶段:加载 Python 文件时会立即执行 decorator(func),把原始函数对象传入并返回 wrapper,再用 wrapper 替换原函数;真正调用函数时,才进入 wrapper 并间接执行原始 func。进阶部分说明多个装饰器的嵌套顺序等价于 decorator1(decorator2(my_func)),也展示了带参数装饰器通过“参数函数 → decorator → wrapper”的三层结构实现可配置行为。文章还专门讨论同步装饰器装饰 async def 的边界:装饰器本身可以是同步函数,因为它只在定义阶段接收函数对象,但包装后的执行阶段必须判断 coroutine,并在异步路径中正确 await,否则会造成调用语义不安全。最后通过 functools.wraps 保留函数名和文档等元信息,帮助读者把装饰器从语法糖理解为函数对象替换、包装执行和元信息维护的组合机制。

Macbook配置开发环境
Python 开发
9 分钟

Macbook配置开发环境

这份笔记面向在 MacBook 上搭建 Python 后端开发环境的开发者,背景是本地工具链、编辑器、终端和 GitHub 连接配置较多,容易在新机器或多项目环境中反复踩坑。内容先给出 VS Code/Cursor 的 Python 调试配置示例,包括用 debugpy 启动 FastAPI 的 uvicorn 模块、调试当前文件、设置 PYTHONPATH,以及在 settings.json 中指定项目虚拟环境解释器、额外分析路径和保存格式化行为。随后补充 Python 与 Git 相关插件选择,并记录 PyCharm 在网络异常时可通过代理设置或开启 TUN 模式处理访问问题。GitHub SSH 部分覆盖 Homebrew 安装 Git、使用 ssh-keygen 生成 RSA 密钥、为多账户区分密钥文件名、启动 ssh-agent、ssh-add 加载私钥、把公钥添加到 GitHub,以及用 ssh -T 验证认证结果;若代理导致 22 端口异常,则参考 GitHub 官方的 HTTPS 端口 SSH 方案。后续还整理了 iTerm2、Oh My Zsh、agnoster 主题的安装入口和 zsh 配置位置,并列出 WebStorm、PyCharm、Docker、Cursor、抓包与远程控制等常用软件。阅读时应结合自己的 ARM 或 x86 架构、代理环境、项目路径和密钥命名调整命令,尤其要始终区分公钥与私钥,避免把私钥内容上传到平台。

环境配置
Python 开发
17 分钟

python 搜索模块解析

这是一篇围绕 Python import 解析机制的排查型笔记,核心对象是 sys.path 如何决定模块查找结果,以及不同启动方式为什么会导致导入行为不一致。文章先说明 sys.path 的主要来源,包括当前脚本目录或工作目录、PYTHONPATH、解释器标准库、site-packages,以及 PyCharm Source Root 自动注入的路径,并强调解释器会按顺序命中后停止搜索。针对常见报错,内容区分了直接运行 python app/module/a.py 与在项目根目录使用 python -m app.module.a 的差异,解释相对导入失败通常是因为模块被当作 __main__ 顶层脚本执行,缺少父包上下文。对于 ModuleNotFoundError: No module named 'app',文章给出的线索是项目根目录不在 sys.path 中,可通过设置 PYTHONPATH、追加路径或改用包方式运行来修正。PyCharm 部分提醒 IDE 的 Source Root 会掩盖命令行、Docker、服务器环境中的路径问题,因此团队更适合统一绝对导入和运行约定。文章还解释了 pip 安装包能在内部使用 from .utils import x 的原因:包位于 site-packages,外部通过 import 包名加载,解释器能识别其包结构。最后补充 __init__.py 在声明包、组织公共 API、配合 __all__ 控制导出和执行初始化逻辑中的作用,适合需要排查导入错误、统一项目结构或理解 IDE 与命令行差异的 Python 开发者。

Python 开发
6 分钟

从 Alpha 到 Final:Python 各阶段版本到底该怎么用

这篇笔记围绕 CPython 主版本的发布周期展开,先交代主流 Python 由 PSF 主导维护,并明确日常使用的官方实现通常指 CPython。正文将每个主版本划分为 Alpha、Beta、RC 和 Final 四个阶段:Alpha 仍在功能开发、接口可能变化,Beta 进入功能冻结并适合库和框架作者做兼容性测试,RC 接近正式版但仍应谨慎用于生产灰度,Final 才是多数项目正式切换的稳定时机。文章用 Python 3.14 的时间线示例说明从 2024 年 10 月 Alpha 到 2025 年 10 月正式发布之间,功能开发、缺陷修复、候选发布和 GA 上线如何衔接。围绕 GIL 的部分补充了 3.12 子解释器独立 GIL、3.13 实验性无 GIL 构建,以及 3.14 继续推进 free-threaded 和多解释器支持的演进边界,提醒读者不要把实验能力等同于默认可用能力。后半部分解释虚拟环境中为什么看不到 ceval.c、listobject.c 等 CPython C 源码:.venv 只是基于已安装解释器生成的运行环境,主要包含可执行文件、配置和第三方库,而解释器核心已编译进动态库或安装目录产物中。对于需要评估 Python 升级时机、安排依赖兼容性测试,或理解 .venv、libpython 动态库与 CPython 源码关系的开发者,这篇笔记提供了一个清晰的判断框架。

Python 开发
9 分钟

asyncio 与 uvloop

这篇笔记聚焦 Python 异步编程中的事件循环机制,以及默认 asyncio 事件循环与 uvloop 的实现差异。内容先把 async def 产生的 coroutine、由事件循环驱动的 Task、表示未来结果的 Future 串起来,说明异步任务如何注册到 event loop,并在网络、磁盘等 I/O 等待期间挂起自身、释放 CPU 去执行其他任务。随后梳理 asyncio 作为 Python 3.4 引入的标准库异步框架,包含事件循环、协程管理、Task/Future、异步 I/O、gather、Queue 和锁等工具,适合 aiohttp、asyncpg、FastAPI、Sanic、爬虫或定时任务等非阻塞场景。后半部分重点比较 uvloop:它以 Cython 编写并基于 libuv,兼容 asyncio 接口,但把事件监听、回调调度、超时处理和部分系统调用封装更多放到 C 层完成,从而减少 Python 层回调、上下文切换和 Future 状态管理带来的开销。文中给出的对比强调,uvloop 在 I/O 密集和高并发 Web、代理、网关服务中更可能改善吞吐量、延迟和调度效率,可在 uvicorn 启动参数中通过 --loop uvloop 启用。需要注意的是,uvloop 不支持 Windows,且对复杂数据处理、机器学习等 CPU 密集任务帮助有限,这类负载应优先考虑多进程或线程池。

Python 开发
13 分钟

FastApi+WebSocket解析

这篇笔记围绕 FastAPI 的基础用法和 WebSocket 集成展开,先说明 FastAPI 依赖 Python 类型提示、自动数据校验与 Swagger/ReDoc 文档生成,适合构建高性能 API 和微服务,但不包含数据库或前端能力。正文从安装 fastapi、uvicorn 开始,给出 main.py 中创建 FastAPI 实例、使用 @app.get 绑定根路径、通过 uvicorn main:app 指定模块与实例并启用 --reload 的最小运行流程。HTTP 路由部分解释了 get、post、put、delete 等路径装饰器的含义,以及函数返回值会被自动转换为 JSON 响应,路径参数也可直接映射到函数参数。WebSocket 部分重点说明其在单个长连接上提供全双工通信的机制,并用 /ws 示例展示 accept、receive_text、send_text、按消息内容 close 的基本收发闭环,可用 ApiFox 等工具测试。进阶内容补充了生产环境关闭 /docs、/redoc、openapi_url 的做法,区分 debug=True 与 uvicorn --reload 的作用,并介绍 lifespan 用于启动和关闭阶段的资源管理。最后通过 APIRouter 拆分 WebSocket 路由、Depends 执行 token 鉴权、query_params 读取 URL 参数、iter_json 处理 JSON 消息,形成从入门运行到结构化实时通信接口的配置参考,适合 FastAPI 初学者、后端开发和需要实现聊天或实时数据通道的开发者阅读。

文章归档
183