PyQt5连接MySQL报Driver not loaded的完整解决方案

发布时间:2026/10/4 5:27:40
PyQt5连接MySQL报Driver not loaded的完整解决方案 1. 问题本质不是代码写错了是环境链断了“PyQt5 使用 QSqlDatabase 连接 MySQL 数据库时 Driver not loaded Driver not loaded”——这行报错我第一次看到时也以为是QSqlDatabase.addDatabase(QMYSQL)写错了或者用户名密码填错了。结果调试两小时发现连数据库服务器的 IP 都没发出去。根本不是逻辑问题而是底层驱动压根没加载成功。这个错误的本质是 PyQt5 的 SQL 插件系统在启动时找不到能和 MySQL 对话的“翻译官”。QSqlDatabase 本身只是个调度员它不直接和 MySQL 打交道而是把 SQL 请求交给一个叫QMYSQL的驱动插件去执行。而这个插件是一个独立的.dllWindows或.soLinux/macOS文件名字通常是qsqlmysql.dll。它要正常工作还得依赖另一个更底层的“语言包”——MySQL 官方提供的libmysql.dllWindows或libmysqlclient.soLinux/macOS。这两者缺一不可且版本必须严格匹配。你可以把整个链路想象成一个跨国电话系统你PyQt5 应用说中文qsqlmysql.dll是你的翻译但它只会说“MySQL方言”不会直接拨号libmysql.dll是国际长途线路接线员负责把“MySQL方言”真正传到远端 MySQL 服务器并把响应原路带回来。一旦中间任何一环缺失、放错位置、版本打架就会报出那个重复两次的“Driver not loaded”。它不是在骂你是在喊“翻译没上岗线路不通”这个错误高频出现在 Windows 平台尤其当你用 pip install pyqt5 安装后直接开干——因为 pip 安装的 PyQt5 二进制包默认不附带任何数据库驱动插件更不会帮你把libmysql.dll放进系统 PATH。它只提供“调度能力”不提供“执行能力”。这是官方设计不是 bug但对新手极其不友好。所以解决它的核心思路从来就不是改 Python 代码而是找到或编译出正确的qsqlmysql.dll把它放到 PyQt5 能自动扫描到的插件目录里确保libmysql.dll在运行时能被qsqlmysql.dll动态加载到验证整个链路是否畅通。下面我会按这个逻辑把每一步拆到螺丝级包括为什么放这里、为什么用这个版本、为什么不能用另一个路径——全是我在三个不同客户现场踩坑后记下的笔记。2. 核心细节解析驱动文件在哪怎么放谁来加载2.1 PyQt5 插件目录结构与加载机制PyQt5 启动时会按固定顺序搜索sqldrivers插件目录。这个搜索路径不是凭空来的而是由QApplication初始化时读取QT_PLUGIN_PATH环境变量再 fallback 到 PyQt5 安装目录下的标准路径。在 Windows 上典型路径是C:\Python39\Lib\site-packages\PyQt5\Qt5\plugins\sqldrivers\注意路径里的Qt5是关键。如果你装的是 PyQt5 5.15.x它捆绑的是 Qt 5.15 的运行时所以插件必须放在Qt5\plugins\下而不是Qt\plugins\或PyQt5\plugins\。我见过太多人把qsqlmysql.dll直接扔进PyQt5\根目录结果 PyQt5 根本不看——因为它只认Qt5\plugins\sqldrivers\这个“户口本”。验证方法很简单在 Python 里加一行调试代码from PyQt5.QtCore import QCoreApplication print(Qt plugin paths:, QCoreApplication.libraryPaths())运行后你会看到类似输出Qt plugin paths: [C:/Python39/Lib/site-packages/PyQt5/Qt5/plugins]这说明 PyQt5 只在这个路径下找插件。如果你的qsqlmysql.dll不在.../plugins/sqldrivers/里它永远看不到。提示不要试图用QCoreApplication.addLibraryPath()动态添加路径。虽然 API 存在但在 QApplication 实例化之后调用基本无效且容易引发插件重复加载冲突。最稳的方式就是把文件放到它默认找的地方。2.2qsqlmysql.dll的三种来源与实操选择你有三条路拿到这个文件每条路的稳定性、兼容性、维护成本都不同路径一从官方 Qt 安装包中提取推荐但需手动Qt 官方离线安装包如Qt 5.15.2 MinGW 64-bit自带完整驱动。下载地址在 qt.io/download选 “Previous Releases” 找 5.15.x。安装后路径为C:\Qt\5.15.2\mingw81_64\plugins\sqldrivers\qsqlmysql.dll⚠️ 注意这里的mingw81_64表示编译器版本。如果你用的是 MSVC 编译的 Python绝大多数 pip 安装的 Python 都是 MSVC 版那么你必须用 MSVC 版 Qt 提取的qsqlmysql.dll否则会报DLL load failed: %1 is not a valid Win32 application。✅ 优势官方出品版本纯净无兼容风险。❌ 劣势需要额外下载 3GB 的 Qt 安装包只为拿一个 DLL。路径二用源码编译最可控适合长期项目从 Qt 源码或 PyQt5 源码中编译qsqlmysql.dll。步骤如下安装对应版本的 Qt SDK含 MySQL 开发头文件设置环境变量MYSQL_INCLUDE指向 MySQL 的include目录MYSQL_LIBS指向lib目录运行qmake -o Makefile INCLUDEPATH... LIBS... mysql.promingw32-make或nmake编译。✅ 优势完全可控可 debug适配任意 MySQL 版本。❌ 劣势门槛高编译失败率高新手三天内大概率放弃。路径三复用已有的 MySQL 安装最快但隐患最多很多开发者电脑上已装 MySQL Server 或 MySQL Connector/C。其安装目录下就有libmysql.dll但qsqlmysql.dll通常没有。不过有个取巧办法用depends.exeDependency Walker打开你本地libmysql.dll看它依赖哪些 DLL比如msvcp140.dll,vcruntime140.dll然后确保这些 VC 运行库已安装。再从网上找一个和你的 Python 编译器匹配的qsqlmysql.dll比如搜 “pyqt5 qsqlmysql.dll msvc2019”。✅ 优势5 分钟搞定适合临时调试。❌ 劣势来源不明可能带病毒版本不匹配导致运行时崩溃我遇到过一次程序在查询后第 7 次点击按钮时静默退出查了两天才发现是 DLL 内存泄漏。我个人在交付客户项目时一律采用路径一 脚本自动化校验。我会写一个check_qt_plugins.py启动时自动检查sqldrivers目录是否存在、qsqlmysql.dll是否可加载、依赖的libmysql.dll是否存在。如果任一环节失败立刻弹窗提示并给出修复链接而不是让客户面对冰冷的 “Driver not loaded”。2.3libmysql.dll的定位与版本陷阱这才是真正的“隐形杀手”。qsqlmysql.dll加载时会动态链接libmysql.dll。但这个 DLL不会从 PyQt5 目录加载而是遵循 Windows 的 DLL 搜索顺序应用程序所在目录系统目录System32PATH环境变量中的目录当前工作目录不推荐依赖。所以最稳妥的做法是把libmysql.dll放在你的.exe所在目录如果是开发态就放在.py文件同目录。这样它一定被第一个找到。但更大的坑在于版本。MySQL 8.0 的libmysql.dll默认启用了 SSL 和新认证插件caching_sha2_password而 Qt 5.15 的qsqlmysql.dll编译时链接的是 MySQL 5.7 的客户端库不支持这些新特性。结果就是连接字符串完全正确QSqlDatabase.open()返回True但一执行query.exec_(SELECT 1)就卡死或抛异常。解决方案只有两个降级 MySQL Server 到 5.7不现实或者在 MySQL Server 上执行ALTER USER your_userlocalhost IDENTIFIED WITH mysql_native_password BY your_password; FLUSH PRIVILEGES;这句话强制用户使用老式密码认证qsqlmysql.dll就能握手成功。注意libmysql.dll的位数32/64必须和你的 Python 解释器完全一致。32 位 Python 必须配 32 位libmysql.dll哪怕你系统是 64 位。我曾在一个客户的工控机上栽跟头——他们用的是 32 位 Python 64 位 MySQL Server结果libmysql.dll是 64 位的qsqlmysql.dll加载时报错%1 is not a valid Win32 application但错误信息根本没提位数问题只说“模块初始化失败”。3. 实操过程从零开始搭建可验证的连接链路3.1 准备工作确认基础环境与工具链先别急着复制粘贴代码。花 3 分钟做这几件事能省掉后面 3 小时排查确认 Python 位数与编译器import platform print(platform.architecture()) # 输出 (32bit, WindowsPE) 或 (64bit, WindowsPE) import sys print(sys.version) # 查看是否含 MSC v.192xMSVC或 GCCMinGW记下结果后面选qsqlmysql.dll时全靠它。确认 MySQL Server 状态打开命令行执行mysql -u root -p -e SELECT VERSION();确保能连上且版本 ≤ 8.0.28Qt 5.15 兼容上限。如果版本太高要么降级要么按上节方法改用户认证方式。下载并解压 MySQL Connector/C去 dev.mysql.com/downloads/connector/c/下载MySQL Connector/C 6.1.11这是最后一个兼容 Qt 5.15 的版本。解压后你会得到lib\libmysql.dll64 位lib\libmysql.libinclude\mysql.h等头文件✅ 为什么是 6.1.11因为它是最后一个用 MySQL 5.7 协议、不强制 SSL 的版本。新版 Connector/C 8.x 默认要求 TLS 1.2Qt 5.15 不支持。3.2 部署qsqlmysql.dll与libmysql.dll假设你的 Python 安装在C:\Python39\项目在D:\myapp\。步骤 1放置qsqlmysql.dll从 Qt 5.15.2 MSVC2019 安装目录拷贝C:\Qt\5.15.2\msvc2019_64\plugins\sqldrivers\qsqlmysql.dll粘贴到C:\Python39\Lib\site-packages\PyQt5\Qt5\plugins\sqldrivers\步骤 2放置libmysql.dll从 MySQL Connector/C 6.1.11 解压目录拷贝mysql-connector-c-6.1.11-winx64\lib\libmysql.dll粘贴到D:\myapp\libmysql.dll即你的.py文件同目录提示不要把libmysql.dll放进C:\Windows\System32。这看似一劳永逸但会导致所有 Python 项目共享同一个 DLL一旦某个项目升级了 MySQL其他项目可能因 ABI 不兼容而崩溃。隔离部署才是工程化思维。3.3 编写最小可验证代码MVCE下面这段代码不是为了功能完整而是为了精准暴露问题环节import sys from PyQt5.QtWidgets import QApplication, QMessageBox from PyQt5.QtSql import QSqlDatabase, QSqlQuery def test_mysql_connection(): # Step 1: 检查驱动是否注册 drivers QSqlDatabase.drivers() print(Available drivers:, drivers) if QMYSQL not in drivers: QMessageBox.critical(None, Error, QMYSQL driver not found!) return False # Step 2: 创建数据库连接 db QSqlDatabase.addDatabase(QMYSQL) db.setHostName(localhost) db.setDatabaseName(testdb) db.setUserName(root) db.setPassword(your_password) # Step 3: 尝试打开此时才真正加载 libmysql.dll if not db.open(): error db.lastError().text() print(Open failed:, error) # 关键区分是认证失败还是 DLL 加载失败 if Driver not loaded in error: QMessageBox.critical(None, Driver Error, qsqlmysql.dll or libmysql.dll missing/corrupted.\n Check plugins/sqldrivers and app directory.) else: QMessageBox.critical(None, Connection Error, error) return False # Step 4: 执行简单查询验证链路 query QSqlQuery(db) if not query.exec_(SELECT 1): print(Query failed:, query.lastError().text()) QMessageBox.critical(None, Query Error, query.lastError().text()) return False print(Success! Connection OK.) return True if __name__ __main__: app QApplication(sys.argv) test_mysql_connection() app.exec_()运行它你会看到控制台逐行输出清晰告诉你卡在哪一步。如果卡在 Step 1说明qsqlmysql.dll没放对位置如果卡在 Step 3 且报 “Driver not loaded”说明libmysql.dll找不到或版本不匹配如果卡在 Step 4大概率是 MySQL 用户权限或网络配置问题。3.4 自动化校验脚本把经验固化成工具我把上面的诊断逻辑封装成一个独立脚本verify_qt_mysql.py每次部署新环境前必跑#!/usr/bin/env python3 # verify_qt_mysql.py import os import sys from pathlib import Path from PyQt5.QtCore import QCoreApplication from PyQt5.QtSql import QSqlDatabase def main(): print( PyQt5 MySQL Driver Verification \n) # 1. 检查 Qt 插件路径 plugin_paths QCoreApplication.libraryPaths() print(1. Qt plugin search paths:) for p in plugin_paths: print(f - {p}) sqldrivers Path(p) / sqldrivers if sqldrivers.exists(): dlls list(sqldrivers.glob(qsql*.dll)) print(f → sqldrivers exists, found {len(dlls)} driver(s): {[d.name for d in dlls]}) else: print(f → sqldrivers NOT found!) # 2. 检查可用驱动 drivers QSqlDatabase.drivers() print(f\n2. Available SQL drivers: {drivers}) if QMYSQL not in drivers: print( ❌ QMYSQL driver missing!) return False else: print( ✅ QMYSQL driver registered.) # 3. 检查 libmysql.dll 依赖 import ctypes try: # 尝试显式加载捕获具体错误 ctypes.CDLL(libmysql.dll) print(\n3. libmysql.dll loadable from current directory.) except OSError as e: print(f\n3. ❌ libmysql.dll load failed: {e}) print( → Please place libmysql.dll in the same directory as this script.) return False print(\n✅ All checks passed. Ready to connect.) return True if __name__ __main__: sys.exit(0 if main() else 1)把它和libmysql.dll放一起双击运行绿色 ✅ 就代表环境 ready。这个脚本我已集成进 CI/CD 流程每次打包.exe前自动执行避免把残缺包发给客户。4. 常见问题与排查技巧实录那些文档里不会写的坑4.1 问题速查表按现象反推根源现象最可能原因排查指令修复动作QSqlDatabase.drivers()不含QMYSQLqsqlmysql.dll未放入Qt5\plugins\sqldrivers\dir C:\Python39\Lib\site-packages\PyQt5\Qt5\plugins\sqldrivers\拷贝正确版本 DLL 到该目录db.open()报Driver not loaded且lastError().text()为空libmysql.dll找不到或位数不匹配dumpbin /headers libmysql.dll | findstr machine用file命令或dumpbin确认 DLL 位数匹配 Python连接成功但查询时报Unknown database xxxMySQL 用户无该库权限或数据库名拼写错误mysql -u root -p -e SHOW DATABASES;GRANT ALL ON xxx.* TO userlocalhost; FLUSH PRIVILEGES;程序启动慢首次查询卡顿 3 秒libmysql.dll启用了 DNS 解析而localhost解析慢ping localhost看响应时间在连接字符串中用127.0.0.1替代localhostQSqlQuery执行 INSERT 后lastInsertId()返回 0表无自增主键或未启用QSqlQuery::executed()DESCRIBE your_table;确保主键字段类型为INT AUTO_INCREMENT4.2 独家避坑技巧来自三次现场救火的经验技巧一用 Process Monitor 实时抓取 DLL 加载行为当一切看起来都对但还是报 “Driver not loaded”就用 Sysinternals 的Process Monitor。过滤条件设为Process Name python.exeOperation LoadImagePath containsmysql运行你的脚本看它到底尝试加载了哪些路径的libmysql.dll以及返回NAME NOT FOUND还是PATH NOT FOUND。有一次我发现它在C:\Windows\SysWOW64\下找 32 位 DLL而我的libmysql.dll放在了SysWOW64外面——原来是因为 Python 是 32 位Windows 自动映射到了 WOW64 目录。技巧二强制指定libmysql.dll路径绕过搜索逻辑如果实在搞不定 DLL 搜索路径可以在 Python 里提前加载import ctypes import os # 假设 libmysql.dll 在脚本同目录 dll_path os.path.join(os.path.dirname(__file__), libmysql.dll) ctypes.CDLL(dll_path) # 强制加载后续 qsqlmysql.dll 就能复用这招在打包成.exe用 PyInstaller时特别管用因为 PyInstaller 会把所有 DLL 打包进_MEIxxxxxx临时目录而qsqlmysql.dll默认找不到它。技巧三用 Dependency Walker 查 DLL 依赖树下载 depends22.exe打开qsqlmysql.dll它会列出所有依赖 DLL。重点看libmysql.dll是否标红找不到msvcp140.dll,vcruntime140.dll是否存在VC 运行库如果libmysql.dll依赖ssleay32.dll和libeay32.dll旧版 OpenSSL而你没放它们也会加载失败。这时要去 OpenSSL 官网下载对应版本的 DLL 补齐。4.3 高频误区纠正为什么你搜到的教程总失效误区“pip install pyqt5-tools 就能解决”pyqt5-tools只包含 Designer 和 uic 工具不包含任何数据库驱动。它甚至不修改 PyQt5 的插件路径。误区“把 libmysql.dll 放进 Python DLLs 目录就行”C:\Python39\DLLs\是 Python 自己的扩展模块目录Qt 的插件加载器根本不看这里。它只认Qt5\plugins\。误区“用 conda install pyqt5.15 就自带驱动”Conda 的 PyQt5 包确实自带部分驱动但qsqlmysql.dll通常被剥离因为 license 问题。你仍需手动提供libmysql.dll。误区“重装 PyQt5 就能修复”pip uninstall pyqt5 pip install pyqt5只会重装 Python 接口层Qt5\plugins\目录里的 DLL 不会被覆盖。除非你加--force-reinstall但风险极高可能破坏其他插件。最后分享一个真实案例上周帮一家医疗设备公司修复他们的数据采集软件。他们用的是 PyQt5 5.15.10 MySQL 8.0.33报错就是标题里的 “Driver not loaded”。我检查发现qsqlmysql.dll是从 Qt 5.12 提取的版本太老libmysql.dll是 MySQL 8.0.33 自带的太新。解决方案是下载 Qt 5.15.2 MSVC2019 安装包用 MySQL Connector/C 6.1.11 的libmysql.dll在 MySQL Server 上批量执行ALTER USER ... IDENTIFIED WITH mysql_native_password。三步做完客户现场测试 20 台设备全部通过。整个过程花了 47 分钟其中 35 分钟在等 Qt 安装包下载。这个错误不是编程能力问题而是环境工程问题。它考验的不是你会不会写db.open()而是你能不能像一个系统工程师那样把 DLL、PATH、位数、版本、权限这五层楼都走通。当你下次再看到 “Driver not loaded”别急着 Google先打开QCoreApplication.libraryPaths()看看 PyQt5 真正想找什么——答案永远在它搜索的路径里。