PyQt5 : sqlite에 확장로드

투스

sqlite를 사용하여 PyQt5 및 Sql 클래스를 시작하고 있습니다. sqlite에 확장을로드하고 싶습니다. 이를 위해서는 sqlite에 대해 런타임에 확장 로딩을 활성화해야합니다. 파이썬 모듈 sqlite3 에서는 enable_load_extension을 통해 활성화됩니다 .

C ++에서 sqlite핸들은 다음과 같이 얻을 수 있습니다 ( https://doc.qt.io/qt-5/qsqldriver.html#handle 에서 가져옴 ) :

QSqlDatabase db = QSqlDatabase::database();
QVariant v = db.driver()->handle();
if (v.isValid() && (qstrcmp(v.typeName(), "sqlite3*") == 0)) {
    // v.data() returns a pointer to the handle
    sqlite3 *handle = *static_cast<sqlite3 **>(v.data());
    if (handle) {
        // ...
    }
}

파이썬에 상응하는 것은

from PyQt5.QtSql import QSqlDatabase

db = QSqlDatabase.addDatabase('QSQLITE')
db.driver().handle()
-> TypeError: unable to convert a C++ 'sqlite3*' instance to a Python object

참고로 Pyside2에서는 핸들 메서드가 노출되지 않습니다.

이것이 잘못된 방법 인 것 같습니다. PyQt5를 통해 sqlite 확장을로드 할 수있는 방법이 있습니까?

Eyllanesc

한 가지 가능한 해결책은 ctypes를 사용하여로드되는 라이브러리를 만드는 것입니다.

이 경우 우분투 리눅스에 대한 솔루션을 보여 주지만 비슷한 단계를 다른 OS에도 적용 할 수 있다고 생각합니다.

라이브러리 컴파일

qsqlite.pro

QT -= gui
QT += sql
TEMPLATE = lib
DEFINES += QSQLITE_LIBRARY
CONFIG += unversioned_libname unversioned_soname
CONFIG += c++11
SOURCES += \
    qsqlite.cpp

HEADERS += \
    qsqlite_global.h \
    qsqlite.h

LIBS += -lsqlite3

qsqlite_global.h

#ifndef QSQLITE_GLOBAL_H
#define QSQLITE_GLOBAL_H

#if defined(_MSC_VER) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#  define Q_DECL_EXPORT __declspec(dllexport)
#  define Q_DECL_IMPORT __declspec(dllimport)
#else
#  define Q_DECL_EXPORT     __attribute__((visibility("default")))
#  define Q_DECL_IMPORT     __attribute__((visibility("default")))
#endif

#if defined(QSQLITE_LIBRARY)
#  define QSQLITE_EXPORT Q_DECL_EXPORT
#else
#  define QSQLITE_EXPORT Q_DECL_IMPORT
#endif

#endif // QSQLITE_GLOBAL_H

qsqlite.h

#ifndef QSQLITE_H
#define QSQLITE_H

#include "qsqlite_global.h"

class QSqlDriver;

extern "C" {
    bool QSQLITE_EXPORT enable_extension(QSqlDriver *ptr, bool enabled);
}

#endif // QSQLITE_H

qsqlite.cpp

#include "qsqlite.h"

#include <sqlite3.h>

#include <QSqlDriver>
#include <QVariant>

bool enable_extension(QSqlDriver *driver, bool enabled)
{
    if(!driver)
        return false;
    QVariant v = driver->handle();
    if (!v.isValid() || !(qstrcmp(v.typeName(), "sqlite3*")==0))
        return false;
    if(sqlite3 *db_handle = *static_cast<sqlite3 **>(v.data())){
        sqlite3_initialize();
        sqlite3_enable_load_extension(db_handle, enabled);
        return true;
    }
    return false;
}
qsqlite/
├── qsqlite.cpp
├── qsqlite_global.h
├── qsqlite.h
└── qsqlite.pro

컴파일하려면 Qt를 사용해야하므로이 경우 python -m pip install aqtinstall다음 명령을 실행하여 aqtinstall ( )을 사용합니다 .

python -m aqt install 5.15.0 linux desktop --outputdir qt
qt/5.15.0/gcc_64/bin/qmake qsqlite
make

참고 : 라이브러리를 컴파일하려면이를 위해 sqlite3 헤더가 있어야합니다 . libsqlite3-dev우분투에 설치해야합니다 : sudo apt install -y --no-install-recommends libsqlite3-dev.

이렇게하면 스크립트 옆에 복사해야하는 libqsqlite.so 라이브러리가 생성됩니다. 예를 들어 다음 코드는 spatialite 모듈 ( sudo apt install -y --no-install-recommends libsqlite3-mod-spatialite)을 로드합니다 .

main.py

from ctypes import CDLL, c_void_p
import os

from PyQt5.QtSql import QSqlDatabase, QSqlQuery

import sip

CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))


def load_spatialite():
    queries = (
        "SELECT load_extension('mod_spatialite')",
        "SELECT InitSpatialMetadata(1)",
    )
    q = QSqlQuery()
    for query in queries:
        if not q.exec_(query):
            print(
                f"Error: cannot load the Spatialite extension ({q.lastError().text()})"
            )
            return False
    return True


def main():
    db = QSqlDatabase.addDatabase("QSQLITE")

    db.setDatabaseName("foo.sqlite")
    if not db.open():
        sys.exit(-1)

    lib = CDLL(os.path.join(CURRENT_DIR, "libqsqlite.so"))
    lib.enable_extension(c_void_p(sip.unwrapinstance(db.driver()).__int__()), True)
    load_spatialite()

    query = QSqlQuery()

    query.exec_("CREATE TABLE my_line(id INTEGER PRIMARY KEY)")
    query.exec_(
        """SELECT AddGeometryColumn("my_line","geom" , 4326, "LINESTRING", 2)"""
    )

    polygon_wkt = "POLYGON ((11 50,11 51,12 51,12 50,11 50))"

    XA = 11
    YA = 52
    XB = 12
    YB = 49

    line_wkt = "LINESTRING({0} {1}, {2} {3})".format(XA, YA, XB, YB)

    query.prepare("""INSERT INTO my_line VALUES (?,GeomFromText(?, 4326))""")

    query.addBindValue(1)
    query.addBindValue(line_wkt)
    query.exec_()

    query.prepare(
        """SELECT astext(st_intersection(geom, GeomFromText(?, 4326))) from my_line WHERE st_intersects(geom, GeomFromText(?, 4326))"""
    )
    query.addBindValue(polygon_wkt)
    query.addBindValue(polygon_wkt)
    query.exec_()

    while query.next():
        for i in range(query.record().count()):
            print(query.value(i))


if __name__ == "__main__":
    main()
├── main.py
└── libqsqlite.so

산출:

LINESTRING(11.333333 51, 11.666667 50)

동일한 라이브러리를 PySide2에 사용할 수 있습니다.

from ctypes import CDLL, c_void_p
import os

from PySide2.QtSql import QSqlDatabase, QSqlQuery

import shiboken2

CURRENT_DIR = os.path.dirname(os.path.realpath(__file__))


def load_spatialite():
    queries = (
        "SELECT load_extension('mod_spatialite')",
        "SELECT InitSpatialMetadata(1)",
    )
    q = QSqlQuery()
    for query in queries:
        if not q.exec_(query):
            print(
                f"Error: cannot load the Spatialite extension ({q.lastError().text()})"
            )
            return False
    return True


def main():
    db = QSqlDatabase.addDatabase("QSQLITE")

    db.setDatabaseName("foo.sqlite")
    if not db.open():
        sys.exit(-1)

    lib = CDLL(os.path.join(CURRENT_DIR, "libqsqlite.so"))
    lib.enable_extension(c_void_p(shiboken2.getCppPointer(db.driver())[0]))
    load_spatialite()

    query = QSqlQuery()

    query.exec_("CREATE TABLE my_line(id INTEGER PRIMARY KEY)")
    query.exec_(
        """SELECT AddGeometryColumn("my_line","geom" , 4326, "LINESTRING", 2)"""
    )

    polygon_wkt = "POLYGON ((11 50,11 51,12 51,12 50,11 50))"

    XA = 11
    YA = 52
    XB = 12
    YB = 49

    line_wkt = "LINESTRING({0} {1}, {2} {3})".format(XA, YA, XB, YB)

    query.prepare("""INSERT INTO my_line VALUES (?,GeomFromText(?, 4326))""")

    query.addBindValue(1)
    query.addBindValue(line_wkt)
    query.exec_()

    query.prepare(
        """SELECT astext(st_intersection(geom, GeomFromText(?, 4326))) from my_line WHERE st_intersects(geom, GeomFromText(?, 4326))"""
    )
    query.addBindValue(polygon_wkt)
    query.addBindValue(polygon_wkt)
    query.exec_()

    while query.next():
        for i in range(query.record().count()):
            print(query.value(i))


if __name__ == "__main__":
    main()

테스트를 위해 여기에서 찾을 수있는 도커를 사용 했습니다 .

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

PyQt4에서 PyQt5로 마이그레이션

분류에서Dev

QML의 ChartView를 PyQt5의 이미지 파일에 저장

분류에서Dev

PyQt5에서 QTableWidget에 파일을 드롭하는 방법

분류에서Dev

PyQt5에 드래그하여 값을 선택하고 목록에 저장

분류에서Dev

PyGame에서 PyQt5로 PyOpenGL을 전송하는 데 혼란

분류에서Dev

PyQt5로 불일치 봇에 제어판 사용

분류에서Dev

pyqt5에서 동적으로 데이터 대시 변경

분류에서Dev

PyQt5로 QTableView에 비동기 데이터 추가

분류에서Dev

PyQt5에서 원을 임의로 움직이나요?

분류에서Dev

Python 3.5 + PyQt5에서 독립 실행 형 exe로

분류에서Dev

연결 문을 qt에서 pyqt5로 변환

분류에서Dev

PyQT5 QTabbar 확장 탭 헤더

분류에서Dev

파일에서로드 할 때 PyQt5 UI가 표시되지 않음

분류에서Dev

pyqt5에서 matplotlib 플롯을 대화식으로 만드는 방법

분류에서Dev

파이썬에서 pyqt4에서 pyqt5로 업그레이드하는 방법

분류에서Dev

작업자 스레드 신호 / 슬롯에 대한 PyQt5 Gui 스레드

분류에서Dev

PyQt5에서 드래그 앤 드롭 인덱스를 얻는 방법

분류에서Dev

메인 모듈 외부에서 QTextedit에 PyQt5 실시간 로깅

분류에서Dev

PyQt5는 pyuic 생성 코드 외부에 eventFilter를 추가합니다.

분류에서Dev

PyQt5 Python에서 QTableWidget의 헤더 내용을 워드 랩하는 방법

분류에서Dev

PyQt5 메서드 서명은 어디에서 찾을 수 있습니까?

분류에서Dev

PyQt5로 바코드 스캔

분류에서Dev

pyqt5에서 lineEdit 입력으로 cwd를 변경하는 방법

분류에서Dev

하위 프로세스를 종료합니다. PyQt5에서 Popen

분류에서Dev

PyQt5에서 항목을 인라인으로 나열하는 방법

분류에서Dev

PyQt5는 열린 메뉴에서 바로 가기를 사용합니다.

분류에서Dev

Python에서 PyQt5를 사용하여 뒤로 버튼 만들기

분류에서Dev

PyQt5 애플리케이션에 대한 대체 OAuth2 로그인

분류에서Dev

PyQt4에서 PyQt5로 마이그레이션하는 동안 직면 한 문제

Related 관련 기사

  1. 1

    PyQt4에서 PyQt5로 마이그레이션

  2. 2

    QML의 ChartView를 PyQt5의 이미지 파일에 저장

  3. 3

    PyQt5에서 QTableWidget에 파일을 드롭하는 방법

  4. 4

    PyQt5에 드래그하여 값을 선택하고 목록에 저장

  5. 5

    PyGame에서 PyQt5로 PyOpenGL을 전송하는 데 혼란

  6. 6

    PyQt5로 불일치 봇에 제어판 사용

  7. 7

    pyqt5에서 동적으로 데이터 대시 변경

  8. 8

    PyQt5로 QTableView에 비동기 데이터 추가

  9. 9

    PyQt5에서 원을 임의로 움직이나요?

  10. 10

    Python 3.5 + PyQt5에서 독립 실행 형 exe로

  11. 11

    연결 문을 qt에서 pyqt5로 변환

  12. 12

    PyQT5 QTabbar 확장 탭 헤더

  13. 13

    파일에서로드 할 때 PyQt5 UI가 표시되지 않음

  14. 14

    pyqt5에서 matplotlib 플롯을 대화식으로 만드는 방법

  15. 15

    파이썬에서 pyqt4에서 pyqt5로 업그레이드하는 방법

  16. 16

    작업자 스레드 신호 / 슬롯에 대한 PyQt5 Gui 스레드

  17. 17

    PyQt5에서 드래그 앤 드롭 인덱스를 얻는 방법

  18. 18

    메인 모듈 외부에서 QTextedit에 PyQt5 실시간 로깅

  19. 19

    PyQt5는 pyuic 생성 코드 외부에 eventFilter를 추가합니다.

  20. 20

    PyQt5 Python에서 QTableWidget의 헤더 내용을 워드 랩하는 방법

  21. 21

    PyQt5 메서드 서명은 어디에서 찾을 수 있습니까?

  22. 22

    PyQt5로 바코드 스캔

  23. 23

    pyqt5에서 lineEdit 입력으로 cwd를 변경하는 방법

  24. 24

    하위 프로세스를 종료합니다. PyQt5에서 Popen

  25. 25

    PyQt5에서 항목을 인라인으로 나열하는 방법

  26. 26

    PyQt5는 열린 메뉴에서 바로 가기를 사용합니다.

  27. 27

    Python에서 PyQt5를 사용하여 뒤로 버튼 만들기

  28. 28

    PyQt5 애플리케이션에 대한 대체 OAuth2 로그인

  29. 29

    PyQt4에서 PyQt5로 마이그레이션하는 동안 직면 한 문제

뜨겁다태그

보관