De functionele manier:
Op deze manier worden de functies weergegeven die u moet instellen om ze in een andere module te kunnen oproepen. Ik heb de contextmanager verwijderd die niet kan worden gebruikt met dit functionele patroon, omdat deze wordt gesloten aan het einde van de functie Open_Conn
. Dus de open_conn
functie maakt een server
object, en het database-object db
, worden ze vervolgens gebeld in close_conn
om gesloten te worden wanneer dat nodig is.
#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_())
De manier van contextmanager:
Het functionele patroon kan worden verbeterd door een contextmanagerklasse te gebruiken om het openings- en het sluitgedeelte automatisch af te handelen. De manager kan alleen de db.cursor
. teruggeven om de query's uit te voeren, blijft de server in de manager. Om cursor
te krijgen , je vangt de waarde terug door de contextmanager binnen de methode __enter__
door als . te gebruiken :with OpenManager() as cursor:
.
Om het te maken, kunt u in principe de opening . verplaatsen code binnen de methode __enter__
(uitgevoerd wanneer u de contextmanager belt) en de afsluiting deel binnen de methode __exit__
(aangeroepen aan het einde van de with statement
blok)
#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')
Met dit patroon kun je de contextmanager in je widget aanroepen, in een with statement
zoals hieronder :
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_())
U kunt ook de verbinding maken met SSHTunnelForwarder
rechtstreeks in de widget om dit te voorkomen en gebruik de contextmanager die door de klas wordt geleverd en maak vervolgens de databaseverbinding binnenin.
De hierboven getoonde aangepaste klasse is slechts een manier om de verbinding met de server en de database binnen één context te combineren om het gemakkelijk te maken als u deze verbindingen op veel plaatsen in uw code nodig hebt.