Nach dem, was wir in So schließen Sie die SQLalchemy-Verbindung in MySQL kommentiert haben , überprüfe ich die Verbindungen, die SQLAlchemy in meiner Datenbank erstellt, und kann sie nicht schließen, ohne Python zu beenden .
Wenn ich diesen Code in einer Python-Konsole ausführe, bleibt die Sitzung geöffnet, bis ich Python verlasse:
from sqlalchemy.orm import sessionmaker
from models import OneTable, get_engine
engine = get_engine(database="mydb")
session = sessionmaker(bind=engine)()
results = session.query(OneTable.company_name).all()
# some work with the data #
session.close()
und die einzige Problemumgehung, die ich gefunden habe, um es zu schließen, ist, engine.dispose()
am Ende anzurufen .
Gemäß den Kommentaren in dem Link, den ich oben gegeben habe, sind meine Fragen jetzt:
- Warum ist es
engine.dispose()
notwendig, Sitzungen zu schließen? - Reicht nicht
session.close()
aus?
python
session
sqlalchemy
fedorqui 'SO hör auf zu schaden'
quelle
quelle
sqlalchemy.pool.NullPool
löst Ihr Problem nicht?AccessShareLock
Postgres-Beziehungen löscht, nachdem dieselect
Abfrage ausgeführt wurdeAntworten:
Es gibt hier eine zentrale Verwirrung über das Wort "Sitzung". Ich bin mir hier nicht sicher, aber es scheint, als würden Sie die SQLAlchemy-Sitzung mit einer MySQL @@ -Sitzung verwechseln. Dies bezieht sich auf den Umfang, in dem Sie zum ersten Mal eine Verbindung zu MySQL herstellen und die Verbindung trennen.
Diese beiden Konzepte sind nicht gleich . Eine SQLAlchemy-Sitzung repräsentiert im Allgemeinen den Umfang einer oder mehrerer Transaktionen bei einer bestimmten Datenbankverbindung.
Daher lautet die Antwort auf Ihre Frage im wahrsten Sinne des Wortes:
session.close()
"Wie wird eine SQLAlchemy-Sitzung ordnungsgemäß geschlossen?".Der Rest Ihrer Frage weist jedoch darauf hin, dass Sie einige Funktionen
Session
wünschen, bei denen beim Schließen einer bestimmten Person auch die eigentliche DBAPI-Verbindung geschlossen werden soll.Dies bedeutet im Grunde, dass Sie das Verbindungspooling deaktivieren möchten . Wie andere Antworten bereits erwähnen, verwenden Sie einfach genug NullPool .
quelle
get_engine(database="mydb", poolclass=NullPool)
ich bekomme es geschlossen, sobald ichsession.close()
. Vielen Dank!session.close()
gibt die Verbindung zum Verbindungspool von Engine zurück und schließt die Verbindung nicht.engine.dispose()
schließt alle Verbindungen des Verbindungspools.Die Engine verwendet keinen Verbindungspool, wenn Sie festlegen
poolclass=NullPool
. Die Verbindung (SQLAlchemy-Sitzung) wird also direkt danach geschlossensession.close()
.quelle
.dispose
für alle anstehenden Commits warten?engine.dispose()
In der LogicBank hatte ich eine Reihe von Tests. Bei jedem Test wurde vor dem Ausführen eine SQLite-Datenbank wie folgt kopiert:
Jeder Test wurde einzeln ausgeführt, schlug jedoch im
discover
Modus fehl . Es stellte sich heraus, dass die Datenbankkopie irgendwie nicht stattfand.Es schien, dass vielleicht unittest nicht seriell ausgeführt wurden. Nicht so - Unittests laufen tatsächlich seriell ab. Das war also nicht das Problem (das protokollieren, um vielleicht jemandem etwas Zeit zu sparen).
Nach einer bemerkenswerten Menge an Thrashing scheint dies daran zu liegen, dass die Datenbank vom vorherigen Test nicht vollständig geschlossen wurde. Irgendwie störte das die obige Kopie. Meins ist nicht zu wundern warum ...
Dank der obigen Beiträge habe ich es folgendermaßen gelöst:
def tearDown(file: str, started_at: str, engine: sqlalchemy.engine.base.Engine, session: sqlalchemy.orm.session.Session): """ close session & engine, banner :param file: caller, usually __file__ :param started_at: eg, str(datetime.now()) :param engine: eg, nw.logic import session, engine :param session: from nw.logic import session, engine :return: """ session.close() engine.dispose(). # NOTE: close required before dispose! print("\n") print("**********************") print("** Test complete, SQLAlchemy session/engine closed for: " + file) print("** Started: " + started_at + " Ended: " + str(datetime.now())) print("**********************")
quelle