Ich habe eine Bibliothek in Python erstellt, die Funktionen für den Zugriff auf eine Datenbank enthält. Dies ist eine Wrapperbibliothek für eine Drittanbieter-Anwendungsdatenbank, die aufgrund der Tatsache geschrieben wurde, dass die Drittanbieter-Anwendung keine anständige API bietet. Jetzt ließ ich ursprünglich jede Funktion eine Datenbankverbindung für die Dauer des Funktionsaufrufs öffnen, was in Ordnung war, bis meine Programmlogik verschachtelte Aufrufe der Funktionen verwendete, bei denen ich dann einige tausend Mal eine bestimmte Funktion aufrufen würde. Das war nicht sehr performant. Die Profilerstellung ergab, dass sich der Overhead im Datenbankverbindungsaufbau befand - einmal pro Funktionsaufruf. Also habe ich die offene Verbindung von innerhalb der Funktion (en) auf das Modul selbst verschoben, so dass die Datenbankverbindung geöffnet wurde, wenn das Bibliotheksmodul importiert wurde. Dies gab mir eine akzeptable Leistung.
Jetzt habe ich zwei Fragen dazu. Muss ich mir erstens Sorgen machen, dass ich die Datenbankverbindung nicht mehr explizit schließe und wie kann ich das mit dieser Einrichtung explizit tun? Zweitens: Fällt das, was ich getan habe, irgendwo in die Nähe des Bereichs der bewährten Verfahren und wie könnte ich das anders angehen?
openConn
Funktion bereit und lassen Sie den Benutzer sie an jede von ihm aufgerufene Funktion weitergeben, damit er den Zusammenhang in einerwith
Anweisung oder in einer anderen Anweisung erfassen kannAntworten:
Es hängt wirklich von der Bibliothek ab, die Sie verwenden. Einige von ihnen könnten die Verbindung selbst schließen (Hinweis: Ich habe die eingebaute sqlite3-Bibliothek überprüft, aber dies ist nicht der Fall). Python ruft einen Destruktor auf, wenn ein Objekt den Gültigkeitsbereich verlässt, und diese Bibliotheken implementieren möglicherweise einen Destruktor, der die Verbindungen ordnungsgemäß schließt.
Dies ist jedoch möglicherweise nicht der Fall! Ich würde empfehlen, wie andere in den Kommentaren, es in ein Objekt zu wickeln.
Dadurch wird Ihre Datenbankverbindung zu Beginn instanziiert und geschlossen, wenn der Bereich, in dem Ihr Objekt instanziiert wurde, nicht mehr gültig ist. Hinweis: Wenn Sie dieses Objekt auf Modulebene instanziieren , bleibt es für Ihre gesamte Anwendung bestehen. Sofern dies nicht beabsichtigt ist, würde ich vorschlagen, Ihre Datenbankfunktionen von den Nicht-Datenbankfunktionen zu trennen.
Glücklicherweise hat Python die Datenbank-API standardisiert , sodass dies mit allen kompatiblen DBs für Sie funktioniert :)
quelle
self
indef query(self,
?db.query('SELECT ...', var)
und es sich darüber beschwert hat, ein drittes Argument zu benötigen.MyDB
Objekt instanziieren :db = MyDB(); db.query('select...', var)
ResourceWarning: unclosed <socket.socket...
Beim Umgang mit Datenbankverbindungen sind zwei Dinge zu beachten:
Vermeiden Sie mehrfache Verbindungsinstanziierungen. Das Öffnen einer Datenbankverbindung durch jede Funktion wird als unangemessen angesehen. Bei der begrenzten Anzahl von Datenbanksitzungen würden Ihnen die Sitzungen ausgehen. Zumindest würde Ihre Lösung nicht skalieren. Verwenden Sie stattdessen das Singleton-Muster. Ihre Klasse würde nur einmal instanziiert. Weitere Informationen zu diesem Muster finden Sie unter Link
Schließen Sie die Verbindung nach dem Beenden der App, nehmen wir an, Sie haben dies nicht getan, und Sie haben mindestens ein Dutzend Instanzen der App, die das Gleiche tun. Zuerst würde alles gut gehen, aber Ihnen würden die Datenbanksitzungen ausgehen und die einzige Lösung Es wäre, den Datenbankserver neu zu starten, was für eine Live-App nicht gut ist. Verwenden Sie daher nach Möglichkeit dieselbe Verbindung.
Um alle diese Konzepte zu verfestigen, sehen Sie sich das folgende Beispiel an, das psycopg2 umschließt
quelle
if Database._instance is None: NameError: name 'Database' is not defined
. Ich kann nicht verstehen, wasDatabase
ist und wie ich das beheben könnte.Postgres.query(Postgres(), some_sql_query)
einewhile
Schleife wiederholt aufrufen würde, würde sie dann die Verbindung in jeder Iteration öffnen und schließen oder sie für die gesamte Zeit derwhile
Schleife offen halten, bis das Programm beendet wird?query()
Funktion zu verwenden, aber es scheint ein Problem mit meinem Code zu geben, wenn ich meine App "parallel" ausführe. Ich habe eine separate Frage dazu gestellt: softwareengineering.stackexchange.com/questions/399582/…Es wäre interessant, Kontext-Manager-Funktionen für Ihre Objekte anzubieten. Dies bedeutet, dass Sie einen Code wie diesen schreiben können:
Dies bietet Ihnen eine praktische Möglichkeit, die Verbindung zur Datenbank automatisch zu schließen, indem Sie die Klasse mit der with-Anweisung aufrufen:
quelle
Eine lange Zeit, um darüber nachzudenken. Heute habe ich den Weg gefunden. Ich weiß nicht, ob es der beste Weg ist. Sie erstellen eine Datei mit dem Namen: conn.py und speichern sie im Ordner /usr/local/lib/python3.5/site-packages/conn/. Ich benutze freebsd und dies ist der Pfad meines Site-Packages-Ordners. in meiner conn.py: conn = "dbname = omnivore user = postgres password = 12345678"
"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" und in dem Skript, das ich Verbindung aufrufen möchte, schreibe ich:
psycopg2 importieren psycopg2.extras importieren psycopg2.extensions
von conn importiere conn versuche: conn = psycopg2.connect (conn.conn) außer: page = "Kann nicht auf die Datenbank zugreifen"
cur = conn.cursor ()
und bla bla ....
Ich hoffe, das ist nützlich
quelle