Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Python verweist auf die Datenbankverbindung in einem anderen Skript

Der funktionale Weg:

Auf diese Weise werden die Funktionen angezeigt, die Sie einrichten müssen, um sie in einem anderen Modul aufrufen zu können. Ich habe den Kontextmanager entfernt, der mit diesem Funktionsmuster nicht verwendet werden kann, da er am Ende der Funktion Open_Conn geschlossen wird . Also die open_conn Funktion erstellt einen server -Objekt und das Datenbankobjekt db , werden sie als nächstes in close_conn aufgerufen um bei Bedarf geschlossen zu werden.

#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_())

Der Kontext-Manager-Weg:

Das funktionale Muster kann verbessert werden, indem eine Kontextmanagerklasse verwendet wird, um den öffnenden und den schließenden Teil automatisch zu handhaben. Der Manager kann nur db.cursor zurückgeben Um die Abfragen auszuführen, bleibt der Server im Manager. Um cursor zu erhalten fangen Sie den vom Kontextmanager zurückgegebenen Wert in der Methode __enter__ ab indem Sie als verwenden :with OpenManager() as cursor: .

Um es zu erstellen, können Sie im Grunde die Öffnung verschieben Code innerhalb der Methode __enter__ (wird ausgeführt, wenn Sie den Kontextmanager aufrufen) und das Schließen Teil innerhalb der Methode __exit__ (wird am Ende der with statement aufgerufen blockieren)

#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')

Mit diesem Muster können Sie den Kontextmanager in Ihrem Widget innerhalb einer with statement aufrufen wie unten:

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_())

Sie könnten die Verbindung auch mit SSHTunnelForwarder herstellen direkt im Widget, um dies zu vermeiden, und verwenden Sie den von der Klasse bereitgestellten Kontextmanager, und erstellen Sie dann die Datenbankverbindung darin.

Die oben gezeigte benutzerdefinierte Klasse ist nur eine Möglichkeit, die Verbindung zum Server und zur Datenbank innerhalb eines Kontexts zu mischen, um es einfach zu machen, wenn Sie diese Verbindungen an vielen Stellen in Ihrem Code benötigen.