Cara fungsional :
Cara ini menunjukkan fungsi yang perlu Anda atur agar dapat memanggilnya di modul lain. Saya menghapus manajer konteks yang tidak dapat digunakan dengan pola fungsional ini, karena ditutup di akhir fungsi Open_Conn
. Jadi open_conn
fungsi membuat server
objek, dan objek database db
, mereka akan dipanggil selanjutnya di close_conn
untuk ditutup bila perlu.
#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_())
Cara pengelola konteks :
Pola fungsional dapat ditingkatkan dengan menggunakan kelas manajer konteks untuk menangani bagian pembuka dan penutup secara otomatis. Manajer hanya dapat mengembalikan db.cursor
untuk mengeksekusi kueri, server tetap berada di dalam manajer. Untuk mendapatkan cursor
, Anda menangkap nilai yang dikembalikan oleh pengelola konteks di dalam metode __enter__
dengan menggunakan sebagai :with OpenManager() as cursor:
.
Untuk membuatnya, pada dasarnya, Anda dapat memindahkan bukaan kode di dalam metode __enter__
(dieksekusi saat Anda akan memanggil pengelola konteks) dan penutupan bagian di dalam metode __exit__
(dipanggil di akhir 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')
Pola ini memungkinkan Anda untuk memanggil pengelola konteks di widget Anda, di dalam with statement
seperti di bawah ini :
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_())
Anda juga dapat membuat koneksi dengan SSHTunnelForwarder
langsung di widget untuk menghindari ini dan gunakan manajer konteks yang disediakan oleh kelas, lalu buat koneksi database di dalamnya.
Kelas kustom yang ditunjukkan di atas hanyalah cara untuk menggabungkan koneksi ke server dan ke database dalam satu konteks untuk memudahkan jika Anda memerlukan koneksi ini di banyak tempat dalam kode Anda.