
当 mysql 数据库密码包含 `@`、`/`、`:` 等 url 保留字符时,sqlalchemy 的连接字符串会解析失败,报错 `getaddrinfo failed`;正确做法是使用 `urllib.parse.quote_plus()` 对密码进行 url 编码。
在使用 SQLAlchemy(配合 Pymysql 或 mysqlclient)连接 MySQL 数据库时,连接字符串格式为:
mysql+driver://username:password@host:port/database
该字符串本质上是一个 URL,因此其中的 username、password、host 和 database 都需满足 URL 编码规范。若密码中包含 @(如 ‘Gspann@123’),URL 解析器会误将 @ 后的内容识别为 host 地址,导致实际解析出错——例如把 Gspann@123 中的 @123 当作主机名的一部分,从而触发 getaddrinfo failed(错误码 errno 11003),最终连接失败。
✅ 正确解决方案:对敏感字段(尤其是密码)进行 URL 编码。推荐仅编码 password 字段(因其最常含特殊字符),使用 python 标准库 urllib.parse.quote_plus:
from urllib.parse import quote_plus from sqlalchemy import create_engine import pandas as pd # 安全编码密码(自动处理 @ / : 等字符) password = "Gspann@123" encoded_password = quote_plus(password) db_connection_str = f"mysql+pymysql://beat_dq_readonly:{encoded_password}@35.187.158.251/beat_results_dev" # 创建引擎(建议添加 pool_recycle 和 echo=False 用于生产环境) db_connection = create_engine( db_connection_str, pool_recycle=3600, # 防止 MySQL 默认 8 小时断连 echo=False # 生产环境关闭 SQL 日志输出 ) # 执行查询 df = pd.read_sql("SELECT * FROM vw_dv_count_rpt", con=db_connection) print(df.head())
⚠️ 注意事项:
- 不要手动替换 @ 为 %40 等编码值——quote_plus 更可靠(它还会处理空格、+、/ 等,并统一转为 %xx 格式);
- 若用户名或数据库名也含特殊字符(罕见但可能),同样需分别编码;
- 确保已安装依赖:pip install pymysql sqlalchemy pandas;
- 避免在代码中硬编码密码,推荐改用环境变量(如 os.getenv(“DB_PASSWORD”))或密钥管理服务;
- 连接失败时,优先检查网络可达性(如 ping 35.187.158.251 或 telnet 35.187.158.251 3306),再排查 URL 编码问题。
通过规范编码密码,可彻底规避因 URL 解析歧义引发的连接异常,确保数据库连接稳定可靠。