La forma funcional:
De esta manera muestra las funciones que necesita configurar para poder llamarlas en otro módulo. Eliminé el administrador de contexto que no se puede usar con este patrón funcional, ya que se cierra al final de la función Open_Conn
. Entonces el open_conn
la función crea un server
objeto, y el objeto de la base de datos db
, serán llamados a continuación en close_conn
para cerrar cuando sea necesario.
#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_())
La forma del administrador de contexto:
El patrón funcional se puede mejorar utilizando una clase de administrador de contexto para manejar la parte de apertura y cierre automáticamente. El administrador solo puede devolver el db.cursor
para ejecutar las consultas, el servidor permanece dentro del administrador. Para obtener cursor
, captura el valor devuelto por el administrador de contexto dentro del método __enter__
usando como :with OpenManager() as cursor:
.
Para crearlo, básicamente, puedes mover la apertura código dentro del método __enter__
(ejecutado cuando llamará al administrador de contexto) y el cierre parte dentro del método __exit__
(llamado al final de la declaración with statement
bloque)
#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')
Este patrón le permite llamar al administrador de contexto en su widget, dentro de una declaración with statement
como a continuación:
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_())
También puede crear la conexión con SSHTunnelForwarder
directamente en el widget para evitar esto y use el administrador de contexto provisto por la clase, luego cree la conexión de la base de datos dentro.
La clase personalizada que se muestra arriba es solo una forma de combinar la conexión con el servidor y la base de datos dentro de un contexto para que sea más fácil si necesita estas conexiones en muchos lugares de su código.