Den funktionelle måde:
På denne måde vises de funktioner, du skal konfigurere for at kunne kalde dem i et andet modul. Jeg fjernede konteksthåndteringen, der ikke kan bruges med dette funktionelle mønster, da det bliver lukket i slutningen af funktionen Open_Conn
. Så open_conn
funktion opretter en server
objekt og databaseobjektet db
, vil de blive kaldt næste i close_conn
for at blive lukket, når det er nødvendigt.
#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_())
Konteksthåndteringsmåden:
Det funktionelle mønster kan forbedres ved at bruge en konteksthåndteringsklasse til at håndtere åbnings- og lukkedelen automatisk. Manageren kan kun returnere db.cursor
for at udføre forespørgslerne forbliver serveren inde i manageren. For at få cursor
, fanger du værdien retur af kontekstadministratoren i metoden __enter__
ved at bruge som :with OpenManager() as cursor:
.
For at oprette den kan du grundlæggende flytte åbningen kode inde i metoden __enter__
(udføres, når du vil kalde kontekstadministratoren) og afslutningen del inde i metoden __exit__
(kaldes i slutningen af with statement
blokere)
#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')
Dette mønster giver dig mulighed for at kalde kontekstadministratoren i din widget, inde i en with statement
som nedenfor :
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_())
Du kan også oprette forbindelsen med SSHTunnelForwarder
direkte i widget'en for at undgå dette og brug konteksthåndteringen, som klassen leverer, og opret derefter databaseforbindelsen inde.
Den tilpassede klasse vist ovenfor er blot en måde at blande forbindelsen til serveren og til databasen i én kontekst for at gøre det nemt, hvis du har brug for disse forbindelser mange steder i din kode.