При нескольких подключениях к БД приложение зависает

Рейтинг: 0Ответов: 1Опубликовано: 12.03.2023

Есть база данных sqlite, в ней 2 таблицы. И есть программа на PyQt5, которая позволяет с ними взаимодействовать. Реализовано так: QTabWidget имеет 2 вкладки (tab), на каждой вкладке свой QTableView. Далее я создаю 2 подключения к бд с помощью QSqlDatabase.addDatabase, открываю их, создаю 2 экземпляра класса QSqlTableModel, передаю им подключения и назначаю на вьюшки.

db_brk = QSqlDatabase.addDatabase('QSQLITE', 'con_brk')
db_rep = QSqlDatabase.addDatabase('QSQLITE', 'con_rep')
db_brk.setDatabaseName('./db/main.db')
db_rep.setDatabaseName('./db/main.db')
db_brk.open()
db_rep.open()
model_brk = QSqlTableModel(self, db=db_brk)
model_rep = QSqlTableModel(self, db=db_rep)
model_brk.setTable('brk')
model_rep.setTable('rep')
model_brk.select()
model_rep.select()
self.view_brk.setModel(model_brk)
self.view_rep.setModel(model_rep)

Проблема: при попытке изменения записей программа "зависает" на некоторое время, на пару секунд, и в дальнейшем, даже если я просто выделяю ячейку точно так же зависает на некоторое время. Если убрать одно подключение QSqlDatabase.addDatabase то все работает мгновенно и без проблем. Так же заметил закономерность: при 2-х подключениях в рабочей папке во время изменений появляется файл *.db-journal и пока он не пропадет программа не отвечает. При одном подключении этот файл не появляется.
screenshot

Вопрос: как мне наладить работу с 2-мя подключениями чтобы был одновременный доступ к 2 таблицам без зависаний? Или я изначально неправильно подошел к архитектуре и не нужно использовать 2 подключения?

Код для воспроизведения main.py

import sys, sqlite3

from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5.QtSql import QSqlDatabase, QSqlTableModel
from ui_design import Ui_MainWindow

# create db for example
with sqlite3.connect('main.db') as con:
    cur = con.cursor()
    cur.execute('CREATE TABLE IF NOT EXISTS brk ("data" int)')
    cur.execute('CREATE TABLE IF NOT EXISTS rep ("data" int)')
    for i in range(1000):
        cur.execute(f'INSERT INTO brk VALUES ({i})')
        cur.execute(f'INSERT INTO rep VALUES ({i})')


class MainWindow(QMainWindow, Ui_MainWindow):

    def __init__(self):
        QMainWindow.__init__(self)
        self.setupUi(self)

        db_brk = QSqlDatabase.addDatabase('QSQLITE', 'con_brk')
        db_rep = QSqlDatabase.addDatabase('QSQLITE', 'con_rep')
        db_brk.setDatabaseName('./main.db')
        db_rep.setDatabaseName('./main.db')
        db_brk.open()
        db_rep.open()
        model_brk = QSqlTableModel(self, db=db_brk)
        model_rep = QSqlTableModel(self, db=db_rep)
        model_brk.setTable('brk')
        model_rep.setTable('rep')
        model_brk.select()
        model_rep.select()
        self.view_brk.setModel(model_brk)
        self.view_rep.setModel(model_rep)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = MainWindow()
    main.show()
    sys.exit(app.exec_())

Код ui.design.py

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1232, 692)
        font = QtGui.QFont()
        font.setPointSize(12)
        MainWindow.setFont(font)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.centralwidget.sizePolicy().hasHeightForWidth())
        self.centralwidget.setSizePolicy(sizePolicy)
        self.centralwidget.setObjectName("centralwidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
        self.verticalLayout.setObjectName("verticalLayout")
        self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
        self.tabWidget.setTabBarAutoHide(False)
        self.tabWidget.setObjectName("tabWidget")
        self.tab_4 = QtWidgets.QWidget()
        self.tab_4.setObjectName("tab_4")
        self.horizontalLayout_11 = QtWidgets.QHBoxLayout(self.tab_4)
        self.horizontalLayout_11.setObjectName("horizontalLayout_11")
        self.view_brk = QtWidgets.QTableView(self.tab_4)
        self.view_brk.setObjectName("view_brk")
        self.view_brk.verticalHeader().setStretchLastSection(False)
        self.horizontalLayout_11.addWidget(self.view_brk)
        self.tabWidget.addTab(self.tab_4, "")
        self.tab_5 = QtWidgets.QWidget()
        self.tab_5.setObjectName("tab_5")
        self.horizontalLayout_9 = QtWidgets.QHBoxLayout(self.tab_5)
        self.horizontalLayout_9.setObjectName("horizontalLayout_9")
        self.view_rep = QtWidgets.QTableView(self.tab_5)
        self.view_rep.setObjectName("view_rep")
        self.horizontalLayout_9.addWidget(self.view_rep)
        self.tabWidget.addTab(self.tab_5, "")
        self.verticalLayout.addWidget(self.tabWidget)
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        self.tabWidget.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_4), _translate("MainWindow", "tab1"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_5), _translate("MainWindow", "tab2"))

Ответы

▲ 0Принят

К одному *.db файлу достаточно одного объекта подключения.