Unable to load QMYSQL Driver on PySide2

1.2k views Asked by At

How can i install and load the Qmysql driver using Pyside2 (pip) with python3.8? I've already tried to download git:qtbase and compiled the driver from there but I had any luck.

2

There are 2 answers

2
eyllanesc On BEST ANSWER

This answer covers not only the installation for Linux but for the other OS, besides that it also applies for pyqt5


The binaries used by Qt are the same ones used by PyQt5/PySide2 since they use the same base code so you will have to compile the plugins.

In this case, to compile the mysql plugin you must follow the official manual, which in summary is:

  1. Install the dependencies, in this case the mysql-connector-c
  2. Install Qt of the same version with which pyqt5/pyside2 was compiled and development tools such as MSVC on windows, build-essentials on Ubuntu, XCode on MacOS, etc.
  3. Download the source code, in this case the qtbase repository.
  4. Compile the plugin.

To find out the version of Qt with the version that the library was compiled with, the following can be used:

  • 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())"

The above generates libqsqlmysql.so, qsqlmysql.dll or libqsqlmysql.dylib depending on the OS. That file must be pasted in the path:

  • 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'))"

To cover all the cases I have created a Github Actions that generates the binaries:

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 }}

The previous code generates the plugin that you can find here.


In the specific case of Ubuntu it can be reduced to:

  • Copy the libqsqlmysql.so file to QT_SQL_DRIVER_PATH.
  • Execute sudo apt install libmysqlclient-dev

In the specific case of Windows it can be reduced to:

0
Nishi On

P.S. almost half of this info is officially published at https://doc.qt.io/qt-6/deployment-plugins.html

I use PySide6 on Windows 10 and %QT_SQL_DRIVER_PATH% does not work for me. What works for PySide6 is the %QT_PLUGIN_PATH% environment variable.

Let's assume that you have built (or downloaded) a SQL driver for Qt platform into C:\projects\my-project-1\qt-plugins\sqldrivers, so that there is qsqlmysql.dll there.

CASE #1: you execute QSqlDatabase.addDatabase("QMYSQL"), but you get the following error:

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

It means that qsqlmysql.dll (a plugin for Qt platform) was not found.

The fix is to define the environment variable %QT_PLUGIN_PATH% and put qsqlmysql.dll into %QT_PLUGIN_PATH%/sqldrivers/. You can even do it in your Python script before invocation of QSqlDatabase.addDatabase:

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

Note, qsqlmysql.dll must be a release version built using MSVC (64-bit since it is year 2022), not MinGW. Debug version fails by some reason in my experience.

If you don't want to define the %QT_PLUGIN_PATH% environment variable, an alternative fix is to copy qsqlmysql.dll into one of these directories: <python-install-dir>/sqldrivers/ or <python-install-dir>/lib/site-packages/PySide6/plugins/sqldrivers/.

Another alternative is to use QCoreApplication.addLibraryPath like this:

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

And yet another alternative is to create <python-install-dir>\qt.conf or <python-install-dir>\qt6.conf with following content:

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

or even so:

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

N.B. qt6.conf is ignored if qt.conf doesn't exist. If you use qt6.conf, you must create an empty qt.conf at least.


CASE #2: you execute QSqlDatabase.addDatabase("QMYSQL"), but you get the following error:

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

It means that qsqlmysql.dll was found, but its dependencies were not. The qsqlmysql.dll additionally requires 3 DLLs: libmysql.dll, libcrypto-1_1-x64.dll, libssl-1_1-x64.dll. These DLLs must be located in %PATH% or in current directory.

N.B. if you place the DLLs near your python script, this won't work if current working directory is different from scripts's location. But you can modify %PATH% even in your Python script. For example, if you copied said DLLs into deps sub-directory of your project:

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

Another possible issues might be:

  • architecture mismatch (some DLLs are 64-bit, while others are 32-bit).
  • binary incompatibility - e.g. if "sqldrivers/qsqlmysql.dll" is built with MinGW or it's a debug version downloaded from https://github.com/thecodemonkey86/

Define the environment variable: set QT_DEBUG_PLUGINS=1 - this might help to troubleshoot such issues.