本文解决的报错 RuntimeError: 'cryptography' package is required for sha256_password or caching_sha2_password auth methods

连 MySQL 报 "cryptography package is required"

本地 SQLite 跑得好好的,换成服务器上的 MySQL 就起不来。原因不在代码,在 MySQL 8 换了默认的密码认证方式。

现象

本地用 SQLite 一切正常,把 .env 里的 DATABASE_URL 换成服务器上的 MySQL 之后,启动直接崩:

RuntimeError: 'cryptography' package is required for sha256_password
or caching_sha2_password auth methods

原因

MySQL 8.0 把默认的密码认证插件从 mysql_native_password 换成了 caching_sha2_password

新的认证方式在传密码时要做 RSA 加密,而 PyMySQL 自己不带加密实现,它依赖 Python 的 cryptography 库。没装这个库,PyMySQL 就没法完成认证握手,于是直接抛异常。

所以这个报错的真实含义是:「我看得懂服务器要求的认证方式,但我缺少完成它所需要的工具。」

解决

装上就行:

pip install cryptography

然后把它写进 requirements.txt,否则换台机器部署又会踩一遍:

PyMySQL==1.1.1
cryptography==44.0.0   # PyMySQL 连 MySQL 8 的 caching_sha2_password 需要

装完重启服务:

systemctl restart blog
journalctl -u blog -n 30

另一条路(不推荐)

网上很多答案会让你把用户的认证方式改回旧的:

ALTER USER 'bloguser'@'localhost'
IDENTIFIED WITH mysql_native_password BY '你的密码';

这样确实也能连上,但是在降级安全性caching_sha2_passwordmysql_native_password 更安全,而且后者在 MySQL 8.4 里已经被默认禁用了。

装一个库 vs 降低数据库安全等级,选前者。

顺手学到的

  1. pip install 装上了不等于解决了——没写进 requirements.txt 的依赖,等于没装,下次换环境照样炸
  2. 报错信息里的 caching_sha2_password 是个可以直接拿去搜的关键词。看到不认识的名词先搜它,而不是搜整句报错
  3. 「本地能跑,服务器不能跑」,九成是环境差异:Python 版本、依赖版本、数据库版本、系统差异

排查清单

下次再遇到「本地好好的,服务器就报错」,按这个顺序查:

python3 --version                    # Python 版本一样吗
pip list | grep -i pymysql           # 依赖装了吗、版本一样吗
mysql --version                      # 数据库版本一样吗
journalctl -u blog -n 50             # 完整报错是什么