Python 持续检查Pyside2上的SQLAlchemy数据库连接
首先,我想弄清楚如何每秒检查数据库状态。这样用户就可以知道数据库是否已启动,而无需单击或触发任何操作。我已经读到,这将产生评论中提到的问题 下面是我的最小可重复性示例:Python 持续检查Pyside2上的SQLAlchemy数据库连接,python,qt,sqlalchemy,pyqt5,pyside2,Python,Qt,Sqlalchemy,Pyqt5,Pyside2,首先,我想弄清楚如何每秒检查数据库状态。这样用户就可以知道数据库是否已启动,而无需单击或触发任何操作。我已经读到,这将产生评论中提到的问题 下面是我的最小可重复性示例: import sys import os import shiboken2 from PySide2 import QtCore, QtGui, QtWidgets from PySide2.QtWidgets import QMainWindow, QFileDialog, QMessageBox, QWidget, QDia
import sys
import os
import shiboken2
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtWidgets import QMainWindow, QFileDialog, QMessageBox, QWidget, QDialog, QProxyStyle
from sqlalchemy import create_engine, inspect
class MyWidget(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.resize(200, 200)
self.path = os.path.abspath(os.path.dirname(sys.argv[0]))
self.button = QtWidgets.QPushButton("Open File")
self.labelFile = QtWidgets.QLabel("empty")
self.labelData = QtWidgets.QLabel("None")
self.layout = QtWidgets.QVBoxLayout()
self.layout.addWidget(self.button)
self.layout.addWidget(self.labelFile)
self.layout.addWidget(self.labelData)
self.setLayout(self.layout)
self.button.clicked.connect(self.open_file)
self.process = None
self.CreateEngine = CreateEngine(self)
self.CreateEngine.result.connect(self.start_timer)
self.CreateEngine.start()
def open_file(self):
x = QFileDialog.getOpenFileName(self,"Just To Spice This Code",self.path,"CSV Files (*.csv)")
self.labelFile.setText(x[0]) #just to check that GUI doesn't freeze
def start_timer(self,engine): #callback from CreateEngine
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(lambda: self.continuously_check(engine))
self.timer.start(1000) #check connetion every second, as real-time as possible
def continuously_check(self,engine): #this gonna get called every second, yes it isn't effective i know
self.process = CheckConnection(self,engine)
self.process.result.connect(self.update_connection_label)
self.process.start()
def update_connection_label(self,x): #update connection status on GUI
self.labelData.setText("DB Status: "+str(x))
def closeEvent(self,event): #to handle QThread: Destroyed while thread is still running
print("begin close event")
if(self.process is not None):
if(shiboken2.isValid(self.process)): #to check whether the object is deleted. ->
self.process.wait() #-> this will get messy when the DB connection is down
self.process.quit() #-> (IMO):since i stack so many CheckConnection objects maybe?
print("end close event")
class CreateEngine(QtCore.QThread): #creating engine on seperate thread so that it wont block GUI
result = QtCore.Signal(object)
def __init__(self, parent):
QtCore.QThread.__init__(self, parent)
self.engine = None
def run(self):
self.engine = create_engine('mysql+pymysql://{}:{}@{}:{}/{}'.format("root","","localhost","3306","adex_admin"))
self.result.emit(self.engine)
class CheckConnection(QtCore.QThread): #constantly called every second, yes its not a good approach ->
result = QtCore.Signal(str) #-> i wonder how to replace all this with something appropriate
def __init__(self, parent,engine):
QtCore.QThread.__init__(self, parent)
self.engine = engine
def run(self):
try:
self.engine.execute('SELECT 1').fetchall()
self.result.emit("Connected")
except:
self.result.emit("Not Connected")
self.deleteLater() #somehow this doesn't do it job very well. maybe blocked?
#-> especially when the connection is busted. this thread gets stuck quite long to finish
if __name__ == "__main__":
#idk why when you start this without connection it's running really slow on showing the status of DB
#you must wait like 4 seconds until the connection status is showed up, which is really bad
#but once it's live. it could read database status really fast
app = QtWidgets.QApplication(sys.argv)
widget = MyWidget()
widget.show()
sys.exit(app.exec_())
我创建这个示例只是为了重现我在真实应用程序中面临的相同问题。因此,问题在于closeEvent花费太长时间来终止检查过程,并阻塞GUI。我创建“closeEvent”的原因是,当应用程序关闭时,我有一个生成[QThread:Destroyed while thread is live running]的事件
此外,当数据库不可访问时,它会使QThread完成的时间比它应该完成的时间长,这与数据库可访问时不同。但是我们可以像我们想要的那样检索状态(实时数据库状态的每一秒)。我也尝试过这种愚蠢的方法
...
def continuously_check(self,engine):
self.process = CheckConnection(self,engine)
self.process.result.connect(self.update_connection_label)
self.process.finished.connect(lambda: QtCore.QTimer.singleShot(1000,self.continuously_check))
self.process.start()
...
希望它不会在线程完成之前继续创建对象(ps:显然这不起作用)。那么,在这个问题上,最好的方法是什么?很抱歉,一次出现多个问题。因此我故意尝试执行“非SQL”异常(例如,通过提供未定义的变量故意创建错误),但线程处理得非常好。所以我认为是SQLAlchemy阻止了线程异常处理,所以我故意尝试了一个“非SQL”异常(例如,通过给出未定义的变量故意创建错误),但线程处理得非常好。所以我认为是SQLAlchemy阻止了线程异常处理