gpt4 book ai didi

Python Sqlite3 数据库锁定,QWidget

转载 作者:搜寻专家 更新时间:2023-10-30 23:40:28 25 4
gpt4 key购买 nike

当我尝试从 pyqt 小部件更新数据库时,我得到一个 sqlite3.OperationalError: database is locked

主窗口显示数据库中的项目列表。双击一个项目时,将弹出一个小部件,其中包含用于修改数据库同一行中的值的选项。

我有 4 个独立的 .py 文件;(我已经删除了大部分代码)

DBmanager.py,包含与数据库交互的所有函数。

class DatabaseUtility:
def __init__(self, databaseFile):
self.db = databaseFile
self.conn = sqlite3.connect(self.db)
self.c = self.conn.cursor()

def ChangeItemQuantity(self, itemName, incramentQuantity):
try:
# Change given item quantity in database
self.c.execute('''
SELECT quantity
FROM items
WHERE itemName=?
''',(itemName,))
print(itemName)
print(incramentQuantity)
current_quantity = self.c.fetchone()
print(current_quantity[0])
new_quantity = current_quantity[0] + incramentQuantity
self.c.execute('''
UPDATE items
SET quantity = ?
WHERE itemName=?
''',(new_quantity, itemName))
self.conn.commit()
except Exception as error:
# Rollback any changes if something goes wrong.
self.conn.rollback()
raise error

def __del__(self):
"""Commit and close database connection when the class is terminated."""
# pass
self.conn.commit()
self.c.close()
self.conn.close()

StartGui.py 包含 GUI 的功能。

import sys
from PyQt4 import QtCore, QtGui
from guiFormat import Ui_MainWindow
from itemWidget import Ui_itemWidget
from DBmanager import DatabaseUtility


class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.db = 'testdb.db'
self.dbUtil = DatabaseUtility(self.db)
self.ui.updateButton.clicked.connect(self.populateTable_default)
self.ui.updateButton.clicked.connect(self.dbUtil.UpdateDatabase)
self.ui.searchButton.clicked.connect(self.populateTable_search)
self.ui.tableWidget.doubleClicked.connect(self.open_item_widget)
self.ui.tableWidget.resizeRowsToContents()

# Populate table on initial startup
self.populateTable_default()

def open_item_widget(self):
self.item_widget = ItemWidget(self)
# self.item_widget.show()
column_count = self.ui.tableWidget.columnCount()
self.item_widget.ui.tableWidget.setColumnCount(column_count)
self.item_widget.ui.tableWidget.setRowCount(1)
column_names = self.dbUtil.GetColumns('items')
self.item_widget.ui.tableWidget.setHorizontalHeaderLabels(column_names)
row = self.ui.tableWidget.currentRow()
for column in range(column_count):
x = self.ui.tableWidget.item(row, column).text()
item_data = QtGui.QTableWidgetItem(str(x))
self.item_widget.ui.tableWidget.setItem(0, column, item_data)
self.item_widget.show()


class ItemWidget(QtGui.QWidget):
def __init__(self, parent=None):
self.db = 'testdb.db'
self.dbUtil2 = DatabaseUtility(self.db)
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_itemWidget()
self.ui.setupUi(self)
self.ui.cancelOkButtonBox.rejected.connect(self.close)
self.ui.cancelOkButtonBox.accepted.connect(self.submit_changes)

def submit_changes(self):
# Get item Name.
item_name = self.ui.tableWidget.item(0,0).text()
# Get number from increment box.
quant_increment = self.ui.QuantSpinBox.value()
alert_incrament = self.ui.alertSpinBox.value()
print('Changing quantity...', item_name, quant_increment)
self.dbUtil2.ChangeItemQuantity(item_name, quant_increment)

self.close()



##======================================================================================================================
##======================================================================================================================
if __name__ == "__main__":
dbUtil = DatabaseUtility('testdb.db')
app = QtGui.QApplication(sys.argv)
mainwindow = MainWindow()
mainwindow.show()
# itemwidget = ItemWidget()
# itemwidget.show()
sys.exit(app.exec_())

Mainwindow.py 是主窗口的 pyqt 设计器的导出。

Itemwidget.py 也是项目小部件的 pyqt 设计器的导出。

谢谢大家的帮助。

最佳答案

sqlite3 文档说:

When a database is accessed by multiple connections, and one of the processes modifies the database, the SQLite database is locked until that transaction is committed.

由于您有两个连接,一个由 MainWindow 打开,另一个由 ItemWidget 打开,您的问题的一个可能原因就是文档所说的。当另一个连接所做的更改未提交时,一个连接会尝试更新数据库。您显示的 ChangeItemQuantity 方法不会发生这种情况,因为它所做的更改会立即提交,但显然 DatabaseUtility 有您未显示的其他方法,例如 更新数据库。如果他们做出的更改没有立即提交,那可能就是问题所在。

MainWindowItemWidget 共享一个连接,看看问题是否消失。您可以通过使 conn 成为 DatabaseUtility 实例的共享属性来做到这一点,而不更改调用者:

class DatabaseUtility:

conn = None

def __init__(self, databaseFile):
self.db = databaseFile
if self.__class__.conn is None:
self.__class__.conn = sqlite3.connect(self.db)
self.c = self.conn.cursor()

此外,虽然这似乎不太可能成为问题,但如果其他进程在同一个 SQLite 数据库上有一个打开的事务,只要该事务处于事件状态,数据库就会被锁定。有些应用程序似乎有保持活跃交易的坏习惯。每当我用 SQLite Browser 打开数据库时,我无法从其他程序对数据库执行任何操作(也许我可以将其关闭,但我从来没有想过如何...)

关于Python Sqlite3 数据库锁定,QWidget,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35517710/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com