Der funktionale Weg:
Auf diese Weise werden die Funktionen angezeigt, die Sie einrichten müssen, um sie in einem anderen Modul aufrufen zu können. Ich habe den Kontextmanager entfernt, der mit diesem Funktionsmuster nicht verwendet werden kann, da er am Ende der Funktion Open_Conn
geschlossen wird . Also die open_conn
Funktion erstellt einen server
-Objekt und das Datenbankobjekt db
, werden sie als nächstes in close_conn
aufgerufen um bei Bedarf geschlossen zu werden.
#OpenConn.py
import MySQLdb
from sshtunnel import SSHTunnelForwarder
def open_conn():
server = SSHTunnelForwarder(
('192.168.0.10', 22),
ssh_password="xxx",
ssh_username="xxx",
remote_bind_address=('localhost', 3306))
server.start()
print('opening server : OK')
db = MySQLdb.connect(host='localhost',
port=server.local_bind_port,
user='xxx',
passwd='xxx',
db='DBNAME')
print('opening database : OK')
return (server, db)
def close_conn(server, db):
db.close()
server.stop()
print('closing connection : OK')
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from ViewClientsUI import Ui_ViewClients
from OpenConn import open_conn, close_conn
class ViewClientsWindow(QtWidgets.QDialog, Ui_ViewClients):
def __init__(self):
super(ViewClientsWindow, self).__init__()
self._new_window = None
self.setupUi(self)
self.data_load()
def data_load(self):
server, db = open_conn()
cursor = db.cursor()
query = "SELECT * FROM Clients"
cursor.execute(query)
results = cursor.fetchall()
self.tableWidget.setRowCount(0)
for row_number, row_data in enumerate(results):
self.tableWidget.insertRow(row_number)
for column_number, data in enumerate(row_data):
self.tableWidget.setItem(row_number, column_number, QtWidgets.QTableWidgetItem(str(data)))
close_conn(server, db)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
gui = ViewClientsWindow()
gui.show()
sys.exit(app.exec_())
Der Kontext-Manager-Weg:
Das funktionale Muster kann verbessert werden, indem eine Kontextmanagerklasse verwendet wird, um den öffnenden und den schließenden Teil automatisch zu handhaben. Der Manager kann nur db.cursor
zurückgeben Um die Abfragen auszuführen, bleibt der Server im Manager. Um cursor
zu erhalten fangen Sie den vom Kontextmanager zurückgegebenen Wert in der Methode __enter__
ab indem Sie als verwenden :with OpenManager() as cursor:
.
Um es zu erstellen, können Sie im Grunde die Öffnung verschieben Code innerhalb der Methode __enter__
(wird ausgeführt, wenn Sie den Kontextmanager aufrufen) und das Schließen Teil innerhalb der Methode __exit__
(wird am Ende der with statement
aufgerufen blockieren)
#OpenConn.py
import MySQLdb
from sshtunnel import SSHTunnelForwarder
class OpenManager(object):
def __init__(self):
self.server =None
self.db = None
# here you could define some parameters and call them next
def __enter__(self):
self.server = SSHTunnelForwarder(
('192.168.0.10', 22),
ssh_password="xxx",
ssh_username="xxx",
remote_bind_address=('localhost', 3306))
self.server.start()
print('opening server : OK')
self.db = MySQLdb.connect(host='localhost',
port=self.server.local_bind_port,
user='xxx',
passwd='xxx',
db='DBNAME')
print('opening database : OK')
return self.db.cursor() #
def __exit__(self, type, value, traceback):
self.db.close()
self.server.stop()
print('closing connection : OK')
Mit diesem Muster können Sie den Kontextmanager in Ihrem Widget innerhalb einer with statement
aufrufen wie unten:
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from ViewClientsUI import Ui_ViewClients
from OpenConn import OpenManager
class ViewClientsWindow(QtWidgets.QDialog, Ui_ViewClients):
def __init__(self):
super(ViewClientsWindow, self).__init__()
self._new_window = None
self.setupUi(self)
self.data_load()
def data_load(self):
with OpenManager() as cursor:
query = "SELECT * FROM Clients"
cursor.execute(query)
results = cursor.fetchall()
self.tableWidget.setRowCount(0)
for row_number, row_data in enumerate(results):
self.tableWidget.insertRow(row_number)
for column_number, data in enumerate(row_data):
self.tableWidget.setItem(row_number, column_number, QtWidgets.QTableWidgetItem(str(data)))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
gui = ViewClientsWindow()
gui.show()
sys.exit(app.exec_())
Sie könnten die Verbindung auch mit SSHTunnelForwarder
herstellen direkt im Widget, um dies zu vermeiden, und verwenden Sie den von der Klasse bereitgestellten Kontextmanager, und erstellen Sie dann die Datenbankverbindung darin.
Die oben gezeigte benutzerdefinierte Klasse ist nur eine Möglichkeit, die Verbindung zum Server und zur Datenbank innerhalb eines Kontexts zu mischen, um es einfach zu machen, wenn Sie diese Verbindungen an vielen Stellen in Ihrem Code benötigen.