Funkční způsob:
Tímto způsobem zobrazíte funkce, které musíte nastavit, abyste je mohli volat v jiném modulu. Odstranil jsem správce kontextu, který nelze použít s tímto funkčním vzorem, protože se zavře na konci funkce Open_Conn
. Takže open_conn
vytvoří server
objekt a databázový objekt db
, budou voláni jako další v close_conn
aby se v případě potřeby zavřel.
#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_())
Způsob správce kontextu:
Funkční vzor lze vylepšit použitím třídy kontextového manažera, která automaticky zpracuje otevírání a zavírání. Správce může vrátit pouze db.cursor
pro provádění dotazů zůstává server uvnitř správce. Chcete-li získat cursor
, zachytíte návrat hodnoty kontextovým manažerem uvnitř metody __enter__
pomocí jako :with OpenManager() as cursor:
.
Chcete-li jej vytvořit, v podstatě můžete přesunout otvor kód uvnitř metody __enter__
(provede se, když zavoláte kontextového manažera) a uzavření část uvnitř metody __exit__
(voláno na konci 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')
Tento vzor vám umožňuje zavolat kontextového manažera ve vašem widgetu uvnitř with statement
jako níže:
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_())
Můžete také vytvořit připojení pomocí SSHTunnelForwarder
přímo ve widgetu, abyste se tomu vyhnuli a použijte kontextového manažera poskytovaného třídou, poté uvnitř vytvořte připojení k databázi.
Výše uvedená vlastní třída je jen způsob, jak spojit připojení k serveru a databázi v jednom kontextu, aby bylo snadné, pokud tato připojení potřebujete na mnoha místech v kódu.