
当 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 解析歧义引发的连接异常,确保数据库连接稳定可靠。










