应安装 Pillow 而非 PIL,因 captcha 依赖 Pillow 且 import 语句为 from PIL import Image;需执行 pip install pillow captcha,若报 ImageDraw 导入错误则降级 Pillow 至兼容版本。

为什么直接 pip install captcha 后 ImageCaptcha 报错“no module named PIL”
这不是 captcha 库的问题,而是它依赖的底层图像库没装全。新版 Pillow 已取代 PIL,但 captcha 的 import 语句仍写的是 from PIL import Image —— 所以你得装 Pillow,而不是试图找早已停更的 PIL。
实操建议:
- 运行
pip install pillow captcha(顺序不重要,但必须两者都装) - 验证是否成功:
python -c "from captcha.image import ImageCaptcha; print('OK')" - 如果报
ImportError: cannot import name 'ImageDraw' from 'PIL',说明 Pillow 版本太新(如 10.0+),降级到pip install "pillow 更稳
生成验证码时中文乱码或字体不生效
ImageCaptcha 默认只认英文,且自带字体路径在 Linux/macOS 下可能指向不存在的系统字体。中文支持必须手动指定字体文件路径,且该字体文件需包含中文字符集(如 NotoSansCJK、simhei.ttf)。
实操建议:
- 下载一个支持中文的 TTF 文件(比如从 Google Fonts 下载
NotoSansCJKsc-Regular.otf),放到项目目录下,例如./fonts/NotoSansCJKsc-Regular.otf - 初始化时传入:
ImageCaptcha(fonts=['./fonts/NotoSansCJKsc-Regular.otf']) - 避免用绝对路径;若部署在 Docker 或无 GUI 环境,确认字体文件被正确 COPY 进镜像,且 Python 进程有读取权限
- 字体文件若损坏或不含中文 glyph,会静默回退到默认字体(显示方框或空格),不是报错,容易误判
Django/Flask 中返回验证码图片的常见响应错误
后端生成的是 PIL Image 对象,不能直接 return,必须转成字节流并设置正确的 Content-Type。常见错误是返回了 base64 字符串却没配前端 src="data:image/png;base64,...",或忘了设 Content-Type: image/png 导致浏览器下载文件而非渲染。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
实操建议(以 Flask 为例):
- 用
BytesIO暂存图片:output = BytesIO(); image.save(output, format='PNG') - 重置指针:
output.seek(0),否则返回空内容 - return
send_file(output, mimetype='image/png')(Flask)或Response(output.getvalue(), mimetype='image/png')(Django) - 别把验证码文本和图片塞进同一个 HTTP 响应体——图片走二进制流,文本走 JSON 或 cookie,否则前端解析失败
验证码文本怎么安全地传给前端校验逻辑
不能把验证码明文放在 HTML 或 API 响应里返回,否则绕过校验。服务端生成后必须绑定到用户本次请求上下文(session / redis / JWT payload),且有过期时间(通常 2–5 分钟)。
实操建议:
- 生成验证码时,同时生成随机字符串(如
uuid4().hex[:8])作为 key,把验证码文本存入 Redis:redis.setex(key, 180, 'aB3x') - 接口返回这个 key 给前端(如 JSON 字段
"captcha_id": "abc123"),前端提交表单时一并带上 - 校验时用该 key 查 Redis,命中则比对、删除(防止重放);未命中或过期即返回“验证码已失效”
- 不要用 session 存——某些负载均衡或无状态部署下 session 不共享,Redis 是更可靠的短时存储选择
生成的图片尺寸、字符长度、干扰线强度这些参数看似简单,但调得太弱会被 OCR 破解,太强又影响真实用户识别。真正上线前得拿手机真机拍几次,看是否能稳定识别——机器视觉和人眼的“可读性”边界,往往比代码逻辑更难调试。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










