无法在 PySide2 上加载 QMYSQL 驱动程序

Unable to load QMYSQL Driver on PySide2

如何使用带有 python3.8 的 Pyside2 (pip) 安装和加载 Qmysql 驱动程序?我已经尝试下载 git:qtbase 并从那里编译驱动程序,但我很幸运。

这个答案不仅包括 Linux 的安装,还包括其他 OS 的安装,此外它还适用于 pyqt5


Qt 使用的二进制文件与 PyQt5/PySide2 使用的二进制文件相同,因为它们使用相同的基本代码,因此您必须编译插件。

在这种情况下,要编译 mysql 插件,您必须遵循 the official manual,总结起来就是:

  1. 安装依赖项,在本例中为 mysql-connector-c
  2. 在pyqt5/pyside2上安装与pyqt5/pyside2编译时相同版本的Qt,在windows上安装MSVC等开发工具,在Ubuntu上安装build-essentials,在XCode上安装build-essentials在 Mac 上OS,等等
  3. 下载源代码,在本例中为 qtbase repository.
  4. 编译插件。

要找出库编译时使用的 Qt 版本,可以使用以下命令:

  • PyQt5
python -c "from PyQt5.QtCore import QT_VERSION_STR; print('Qt version', QT_VERSION_STR)"
  • PySide2
python -c "from PySide2.QtCore import qVersion; print('Qt version', qVersion())"

以上根据OS生成libqsqlmysql.so、qsqlmysql.dll或libqsqlmysql.dylib。该文件必须粘贴在路径中:

  • PyQt5:
python -c "import os; from PyQt5.QtCore import QLibraryInfo; print('QT_SQL_DRIVER_PATH', os.path.join(QLibraryInfo.location(QLibraryInfo.PrefixPath), 'plugins', 'sqldrivers'))"
  • PySide2:
python -c "import os; from PySide2.QtCore import QLibraryInfo; print('QT_SQL_DRIVER_PATH', os.path.join(QLibraryInfo.location(QLibraryInfo.PrefixPath), 'plugins', 'sqldrivers'))"

为了涵盖所有情况,我创建了一个 Github 生成二进制文件的操作:

mysql_plugin.yml

name: generate_mysql_plugin

on: [push]

jobs:
  ci:
    name: ${{ matrix.os.name }} Qt-${{ matrix.qt.qt_version }}
    runs-on: ${{ matrix.os.runs-on }}
    strategy:
      fail-fast: false
      matrix:
        os:
          - name: Windows
            extension: "dll"
            runs-on: windows-2019
          - name: Linux
            extension: "so"
            runs-on: ubuntu-20.04
          - name: MacOS
            extension: "dylib"
            runs-on: macos-10.15
        qt:
          - name: 5.15
            qt_version: 5.15.0
    steps:
      - name: Checkout
        uses: actions/checkout@v1
      - name: Install Qt
        uses: jurplel/install-qt-action@v2
        with:
          version: ${{ matrix.qt.qt_version }}
          dir: ${{ github.workspace }}/qt/
      - name: clone qtbase
        run: git clone -b ${{ matrix.qt.qt_version }} https://code.qt.io/qt/qtbase.git
      - name: Compile mysql plugin on Windows
        if: matrix.os.name == 'Windows'
        shell: cmd
        run: |
          choco install wget
          wget https://downloads.mysql.com/archives/get/p/19/file/mysql-connector-c-6.1.11-winx64.zip
          unzip mysql-connector-c-6.1.11-winx64.zip
          copy /y "mysql-connector-c-6.1.11-winx64\lib\libmysql.dll" .
          call "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat"
          cd qtbase/src/plugins/sqldrivers
          qmake -- MYSQL_INCDIR="${{ github.workspace }}\mysql-connector-c-6.1.11-winx64\include" MYSQL_LIBDIR="${{ github.workspace }}\mysql-connector-c-6.1.11-winx64\lib"
          nmake sub-mysql
          nmake install
      - name: Compile mysql plugin on Linux
        if: matrix.os.name == 'Linux'
        run: |
          wget https://downloads.mysql.com/archives/get/p/19/file/mysql-connector-c-6.1.11-linux-glibc2.12-x86_64.tar.gz
          tar zxvf mysql-connector-c-6.1.11-linux-glibc2.12-x86_64.tar.gz
          sudo cp mysql-connector-c-6.1.11-linux-glibc2.12-x86_64/lib/*.so /usr/lib/x86_64-linux-gnu
          sudo apt-get install freetds-dev
          cd qtbase/src/plugins/sqldrivers
          qmake
          cd mysql
          qmake
          make
          make install
      - name: Compile mysql plugin on MacOS
        if: matrix.os.name == 'MacOs'
        run: |
          brew install wget
          wget https://cdn.mysql.com/archives/mysql-connector-c/mysql-connector-c-6.1.11-macos10.12-x86_64.tar.gz
          tar zxvf mysql-connector-c-6.1.11-macos10.12-x86_64.tar.gz
          sudo cp mysql-connector-c-6.1.11-macos10.12-x86_64/lib/libmysqlclient.dylib mysql-connector-c-6.1.11-macos10.12-x86_64/lib/libmysqlclient_r.dylib
          sudo cp mysql-connector-c-6.1.11-macos10.12-x86_64/lib/libmysqlclient.18.dylib mysql-connector-c-6.1.11-macos10.12-x86_64/lib/libmysqlclient_r.18.dylib

          sudo cp mysql-connector-c-6.1.11-macos10.12-x86_64/lib/*.dylib /usr/local/lib
          cd qtbase/src/plugins/sqldrivers
          qmake -- MYSQL_PREFIX="${{ github.workspace }}/mysql-connector-c-6.1.11-macos10.12-x86_64"
          make sub-mysql
          cd mysql
          make install
      - name: upload
        uses: actions/upload-artifact@v2
        with:
          path: qtbase/src/plugins/sqldrivers/plugins/sqldrivers/*qsqlmysql.${{ matrix.os.extension }}
          name: mysqlplugin-${{ matrix.os.name }}-Qt${{ matrix.qt.name }}

前面的代码生成了你可以找到的插件here


在Ubuntu的具体情况下可以简化为:

  • libqsqlmysql.so 文件复制到 QT_SQL_DRIVER_PATH。
  • 执行sudo apt install libmysqlclient-dev

在Windows的具体情况下可以简化为:

P.S。几乎一半的信息在 https://doc.qt.io/qt-6/deployment-plugins.html

上正式发布

我在 Windows 10 上使用 PySide6,%QT_SQL_DRIVER_PATH% 对我不起作用。 适用于 PySide6 的是 %QT_PLUGIN_PATH% 环境变量。

假设您已经为 Qt 平台构建(或下载)了一个 SQL 驱动程序到 C:\projects\my-project-1\qt-plugins\sqldrivers,因此那里有 qsqlmysql.dll

CASE #1: 你执行 QSqlDatabase.addDatabase("QMYSQL"),但你得到以下错误:

QSqlDatabase: QMYSQL driver not loaded
QSqlDatabase: available drivers: QSQLITE QODBC QPSQL

表示没有找到qsqlmysql.dll(Qt平台的插件)

修复就是定义环境变量%QT_PLUGIN_PATH%,把qsqlmysql.dll放到%QT_PLUGIN_PATH%/sqldrivers/中。您甚至可以在 Python 脚本 之前 调用 QSqlDatabase.addDatabase:

os.environ['QT_PLUGIN_PATH'] = r'C:\projects\my-project-1\qt-plugins'

注意,qsqlmysql.dll 必须是使用 MSVC(64 位,因为是 2022 年)构建的发行版本,而不是 MinGW。根据我的经验,调试版本由于某种原因失败。

如果您不想定义 %QT_PLUGIN_PATH% 环境变量,另一种解决方法 是将 qsqlmysql.dll 复制到 个目录:<python-install-dir>/sqldrivers/<python-install-dir>/lib/site-packages/PySide6/plugins/sqldrivers/.

另一种选择 是这样使用 QCoreApplication.addLibraryPath

    app = QCoreApplication(sys.argv)
    app.addLibraryPath(r'C:\projects\my-project-1\qt-plugins')

还有另一种选择是创建 <python-install-dir>\qt.conf<python-install-dir>\qt6.conf 具有以下内容:

[Paths]
Prefix=C:/projects/my-project-1
Plugins=qt-plugins

还是这样:

[Paths]
Plugins=C:/projects/my-project-1/qt-plugins

N.B。如果 qt.conf 不存在,qt6.conf 将被忽略。如果您使用 qt6.conf,您 必须 至少创建一个空的 qt.conf


CASE #2: 你执行了 QSqlDatabase.addDatabase("QMYSQL"),但是你得到了以下错误:

QSqlDatabase: QMYSQL driver not loaded
QSqlDatabase: available drivers: QMARIADB QMYSQL QSQLITE QODBC QPSQL

表示找到了qsqlmysql.dll,但是它的依赖没有qsqlmysql.dll 还需要 3 个 DLL:libmysql.dlllibcrypto-1_1-x64.dlllibssl-1_1-x64.dll。 这些 DLL 必须位于 %PATH% 或当前目录中。

N.B。如果将 DLL 放在 python 脚本附近,如果当前工作目录与脚本的位置不同,这将不起作用。但是您甚至可以在 Python 脚本中修改 %PATH%。 例如,如果您将所述 DLL 复制到项目的 deps sub-directory 中:

os.environ["PATH"] += os.pathsep + os.path.join(os.path.dirname(__file__), 'deps')

另一个可能的问题可能是:

  • 体系结构不匹配(一些 DLL 是 64 位的,而另一些是 32 位的)。
  • 二进制不兼容 - 例如如果“sqldrivers/qsqlmysql.dll”是使用 MinGW 构建的或者它是从 https://github.com/thecodemonkey86/
  • 下载的调试版本

定义环境变量:set QT_DEBUG_PLUGINS=1 - 这可能有助于解决此类问题。