Il modo funzionale:
In questo modo vengono mostrate le funzioni che è necessario impostare per poterle richiamare in un altro modulo. Ho rimosso il gestore del contesto che non può essere utilizzato con questo pattern funzionale, poiché viene chiuso alla fine della funzione Open_Conn
. Quindi il open_conn
la funzione crea un server
oggetto e l'oggetto database db
, verranno chiamati successivamente in close_conn
chiudersi quando necessario.
#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_())
Il modo di gestione del contesto:
Il modello funzionale può essere migliorato utilizzando una classe di gestione del contesto per gestire automaticamente l'apertura e la parte di chiusura. Il gestore può restituire solo il db.cursor
per eseguire le query, il server rimane all'interno del gestore. Per ottenere il cursor
, catturi il valore restituito dal gestore del contesto all'interno del metodo __enter__
utilizzando come :with OpenManager() as cursor:
.
Per crearlo, in pratica, puoi spostare l'apertura codice all'interno del metodo __enter__
(eseguito quando chiamerai il gestore del contesto) e la chiusura parte all'interno del metodo __exit__
(chiamato alla fine del with statement
blocco)
#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')
Questo modello ti consente di chiamare il gestore del contesto nel tuo widget, all'interno di un with statement
come di seguito:
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_())
Puoi anche creare la connessione con SSHTunnelForwarder
direttamente nel widget per evitare ciò e utilizzare il gestore di contesto fornito dalla classe, quindi creare la connessione al database all'interno.
La classe personalizzata mostrata sopra è solo un modo per combinare la connessione al server e al database all'interno di un contesto per semplificare se hai bisogno di queste connessioni in molti punti del tuo codice.