SQLAlchemy 2.0 Dokumentation
- Vorher: Grundlagen der Core API
- Nächste: Laufzeitinspektions-API
- Nach oben: Startseite
- Auf dieser Seite
Ereignisse¶
SQLAlchemy enthält eine Ereignis-API, die eine Vielzahl von Hooks in die Interna von SQLAlchemy Core und ORM veröffentlicht.
Ereignisregistrierung¶
Die Anmeldung zu einem Ereignis erfolgt über einen einzigen API-Punkt, die Funktion listen(), oder alternativ über den Dekorator listens_for(). Diese Funktionen akzeptieren ein Ziel, einen String-Identifikator, der das abzufangende Ereignis identifiziert, und eine vom Benutzer definierte Listener-Funktion. Zusätzliche Positions- und Schlüsselwortargumente für diese beiden Funktionen können von spezifischen Ereignistypen unterstützt werden, die alternative Schnittstellen für die gegebene Ereignisfunktion angeben oder Anweisungen bezüglich sekundärer Ereignisziele basierend auf dem gegebenen Ziel liefern können.
Der Name eines Ereignisses und die Argumentensignatur einer entsprechenden Listener-Funktion werden von einer klassengebundenen Spezifikationsmethode abgeleitet, die an eine Markierungsklasse gebunden ist, die in der Dokumentation beschrieben ist. Zum Beispiel gibt die Dokumentation für PoolEvents.connect() an, dass der Ereignisname "connect" lautet und dass eine vom Benutzer definierte Listener-Funktion zwei Positionsargumente erhalten sollte
from sqlalchemy.event import listen
from sqlalchemy.pool import Pool
def my_on_connect(dbapi_con, connection_record):
print("New DBAPI connection:", dbapi_con)
listen(Pool, "connect", my_on_connect)Die Anmeldung mit dem Dekorator listens_for() sieht so aus
from sqlalchemy.event import listens_for
from sqlalchemy.pool import Pool
@listens_for(Pool, "connect")
def my_on_connect(dbapi_con, connection_record):
print("New DBAPI connection:", dbapi_con)Stil für benannte Argumente¶
Es gibt verschiedene Arten von Argumentenstilen, die von Listener-Funktionen akzeptiert werden können. Am Beispiel von PoolEvents.connect() empfängt diese Funktion die Argumente dbapi_connection und connection_record. Wir können diese Argumente nach Namen empfangen, indem wir eine Listener-Funktion einrichten, die **keyword Argumente akzeptiert, indem wir named=True entweder an listen() oder listens_for() übergeben
from sqlalchemy.event import listens_for
from sqlalchemy.pool import Pool
@listens_for(Pool, "connect", named=True)
def my_on_connect(**kw):
print("New DBAPI connection:", kw["dbapi_connection"])Bei der Verwendung von benanntem Argument-Passing werden die in der Funktionsargumentenspezifikation aufgeführten Namen als Schlüssel im Wörterbuch verwendet.
Der benannte Stil übergibt alle Argumente nach Namen, unabhängig von der Funktionssignatur, so dass spezifische Argumente auch in beliebiger Reihenfolge aufgeführt werden können, solange die Namen übereinstimmen
from sqlalchemy.event import listens_for
from sqlalchemy.pool import Pool
@listens_for(Pool, "connect", named=True)
def my_on_connect(dbapi_connection, **kw):
print("New DBAPI connection:", dbapi_connection)
print("Connection record:", kw["connection_record"])Oben teilt die Anwesenheit von **kw listens_for() mit, dass Argumente nach Namen und nicht positionsweise an die Funktion übergeben werden sollen.
Ziele¶
Die Funktion listen() ist in Bezug auf Ziele sehr flexibel. Sie akzeptiert im Allgemeinen Klassen, Instanzen dieser Klassen sowie verwandte Klassen oder Objekte, von denen das entsprechende Ziel abgeleitet werden kann. Zum Beispiel akzeptiert das oben erwähnte "connect"-Ereignis Engine-Klassen und -Objekte sowie Pool-Klassen und -Objekte
from sqlalchemy.event import listen
from sqlalchemy.pool import Pool, QueuePool
from sqlalchemy import create_engine
from sqlalchemy.engine import Engine
import psycopg2
def connect():
return psycopg2.connect(user="ed", host="127.0.0.1", dbname="test")
my_pool = QueuePool(connect)
my_engine = create_engine("postgresql+psycopg2://ed@localhost/test")
# associate listener with all instances of Pool
listen(Pool, "connect", my_on_connect)
# associate listener with all instances of Pool
# via the Engine class
listen(Engine, "connect", my_on_connect)
# associate listener with my_pool
listen(my_pool, "connect", my_on_connect)
# associate listener with my_engine.pool
listen(my_engine, "connect", my_on_connect)Modifikatoren¶
Einige Listener erlauben die Übergabe von Modifikatoren an listen(). Diese Modifikatoren bieten manchmal alternative Aufrufsignaturen für Listener. Wie bei ORM-Ereignissen können einige Ereignis-Listener einen Rückgabewert haben, der die nachfolgende Verarbeitung modifiziert. Standardmäßig erfordert kein Listener einen Rückgabewert, aber durch die Übergabe von retval=True kann dieser Wert unterstützt werden
def validate_phone(target, value, oldvalue, initiator):
"""Strip non-numeric characters from a phone number"""
return re.sub(r"\D", "", value)
# setup listener on UserContact.phone attribute, instructing
# it to use the return value
listen(UserContact.phone, "set", validate_phone, retval=True)Ereignisse und Multiprocessing¶
Die Ereignis-Hooks von SQLAlchemy werden mit Python-Funktionen und -Objekten implementiert, sodass sich Ereignisse über Python-Funktionsaufrufe verbreiten. Python-Multiprocessing folgt der gleichen Denkweise wie OS-Multiprocessing, z. B. einem Elternprozess, der einen Kindprozess forkt. Daher können wir das Verhalten des SQLAlchemy-Ereignissystems anhand desselben Modells beschreiben.
In einem Elternprozess registrierte Ereignis-Hooks sind in neuen Kindprozessen vorhanden, die nach der Registrierung der Hooks von diesem Elternteil ausgehen, da der Kindprozess beim Start eine Kopie aller vorhandenen Python-Strukturen vom Elternteil erhält. Kindprozesse, die bereits vor der Registrierung der Hooks existieren, erhalten diese neuen Ereignis-Hooks nicht, da Änderungen an Python-Strukturen in einem Elternprozess nicht an Kindprozesse weitergegeben werden.
Die Ereignisse selbst sind Python-Funktionsaufrufe, die keine Möglichkeit haben, sich zwischen Prozessen zu verbreiten. Das Ereignissystem von SQLAlchemy implementiert keine Interprozesskommunikation. Es ist möglich, Ereignis-Hooks zu implementieren, die Python-Interprozessnachrichten innerhalb von ihnen verwenden, dies müsste jedoch vom Benutzer implementiert werden.
Ereignisreferenz¶
Sowohl SQLAlchemy Core als auch SQLAlchemy ORM bieten eine breite Palette von Ereignis-Hooks
Core-Ereignisse – diese werden in Core Events beschrieben und umfassen Ereignis-Hooks, die spezifisch für den Lebenszyklus des Verbindungspools, die Ausführung von SQL-Anweisungen, den Transaktionslebenszyklus sowie die Erstellung und das Abbauen von Schemata sind.
ORM-Ereignisse – diese werden in ORM Events beschrieben und umfassen Ereignis-Hooks, die spezifisch für die Instrumentierung von Klassen und Attributen, Hooks zur Objektinitialisierung, Hooks zum Ändern von Attributen, Sitzungsstatus, Flush- und Commit-Hooks, Mapper-Initialisierung, Objekt-/Ergebnispopulation und Per-Instanz-Persistenz-Hooks sind.
API-Referenz¶
| Objektname | Beschreibung |
|---|---|
contains(target, identifier, fn) |
Gibt True zurück, wenn das angegebene Ziel/Identifikator/fn zum Zuhören eingerichtet ist. |
listen(target, identifier, fn, *args, **kw) |
Registriert eine Listener-Funktion für das angegebene Ziel. |
listens_for(target, identifier, *args, **kw) |
Dekoriert eine Funktion als Listener für das angegebene Ziel + Identifikator. |
remove(target, identifier, fn) |
Entfernt einen Ereignis-Listener. |
- function sqlalchemy.event.listen(target: Any, identifier: str, fn: Callable[[...], Any], *args: Any, **kw: Any) → None¶
Registriert eine Listener-Funktion für das angegebene Ziel.
Die Funktion
listen()ist Teil der primären Schnittstelle für das Ereignissystem von SQLAlchemy, dokumentiert unter Events.z. B.
from sqlalchemy import event from sqlalchemy.schema import UniqueConstraint def unique_constraint_name(const, table): const.name = "uq_%s_%s" % (table.name, list(const.columns)[0].name) event.listen( UniqueConstraint, "after_parent_attach", unique_constraint_name )
- Parameter:
insert¶ (bool) – Das Standardverhalten für Ereignishandler besteht darin, die dekorierte, benutzerdefinierte Funktion beim Entdecken an eine interne Liste registrierter Ereignis-Listener anzuhängen. Wenn ein Benutzer eine Funktion mit
insert=Trueregistriert, fügt SQLAlchemy (stellt voran) die Funktion beim Entdecken in die interne Liste ein. Dieses Feature wird von den SQLAlchemy-Maintainern normalerweise nicht verwendet oder empfohlen, wird aber bereitgestellt, um sicherzustellen, dass bestimmte benutzerdefinierte Funktionen vor anderen ausgeführt werden können, z. B. beim Ändern des sql_mode in MySQL.named¶ (bool) – Bei Verwendung von benanntem Argument-Passing werden die in der Funktionsargumentenspezifikation aufgeführten Namen als Schlüssel im Wörterbuch verwendet. Siehe Named Argument Styles.
once¶ (bool) – Private/interne API-Nutzung. Veraltet. Dieser Parameter würde gewährleisten, dass eine Ereignisfunktion nur einmal pro angegebenem Ziel ausgeführt wird. Er impliziert jedoch keine automatische De-Registrierung der Listener-Funktion; die Zuordnung einer beliebig hohen Anzahl von Listenern ohne explizites Entfernen führt zu unbegrenztem Speicherwachstum, auch wenn
once=Trueangegeben ist.propagate¶ (bool) – Das Schlüsselwortargument
propagateist bei der Arbeit mit ORM-Instrumentierung und Mapping-Ereignissen verfügbar. SieheMapperEventsundMapperEvents.before_mapper_configured()für Beispiele.retval¶ (bool) –
Dieses Flag gilt nur für bestimmte Ereignis-Listener, von denen jeder eine Dokumentation enthält, die erklärt, wann er verwendet werden sollte. Standardmäßig erfordert kein Listener einen Rückgabewert. Einige Listener unterstützen jedoch spezielle Verhaltensweisen für Rückgabewerte und geben in ihrer Dokumentation an, dass das Flag
retval=Trueerforderlich ist, damit ein Rückgabewert verarbeitet werden kann.Ereignis-Listener-Suiten, die
listen.retvalverwenden, umfassenConnectionEventsundAttributeEvents.
Hinweis
Die Funktion
listen()kann nicht gleichzeitig aufgerufen werden, während das Zielereignis ausgeführt wird. Dies hat Auswirkungen auf die Thread-Sicherheit und bedeutet auch, dass ein Ereignis nicht innerhalb der Listener-Funktion für sich selbst hinzugefügt werden kann. Die Liste der auszuführenden Ereignisse befindet sich in einer veränderlichen Sammlung, die während der Iteration nicht geändert werden kann.Ereignisregistrierung und -entfernung sind nicht als "Hochgeschwindigkeitsoperationen" gedacht; sie sind Konfigurationsoperationen. Für Systeme, die sich schnell und in großem Umfang mit Ereignissen verbinden und trennen müssen, verwenden Sie eine veränderliche Struktur, die von einer einzelnen Listener-Funktion aus verwaltet wird.
- function sqlalchemy.event.listens_for(target: Any, identifier: str, *args: Any, **kw: Any) → Callable[[Callable[[...], Any]], Callable[[...], Any]]¶
Dekoriert eine Funktion als Listener für das angegebene Ziel + Identifikator.
Der Dekorator
listens_for()ist Teil der primären Schnittstelle für das Ereignissystem von SQLAlchemy, dokumentiert unter Events.Diese Funktion teilt im Allgemeinen die gleichen Schlüsselwortargumente wie
listen().z. B.
from sqlalchemy import event from sqlalchemy.schema import UniqueConstraint @event.listens_for(UniqueConstraint, "after_parent_attach") def unique_constraint_name(const, table): const.name = "uq_%s_%s" % (table.name, list(const.columns)[0].name)
Eine gegebene Funktion kann auch nur für die erste Ausführung des Ereignisses mit dem Argument
onceaufgerufen werden@event.listens_for(Mapper, "before_configure", once=True) def on_config(): do_config()
Warnung
Das Argument
onceimpliziert keine automatische De-Registrierung der Listener-Funktion, nachdem sie zum ersten Mal aufgerufen wurde; ein Listener-Eintrag bleibt mit dem Zielobjekt verbunden. Die Zuordnung einer beliebig hohen Anzahl von Listenern ohne explizites Entfernen führt zu unbegrenztem Speicherwachstum, auch wennonce=Trueangegeben ist.Siehe auch
listen()– allgemeine Beschreibung des Ereignis-Listenings
- function sqlalchemy.event.remove(target: Any, identifier: str, fn: Callable[[...], Any]) → None¶
Entfernt einen Ereignis-Listener.
Die Argumente hier sollten exakt denen entsprechen, die an
listen()übergeben wurden; alle Registrierungen von Ereignissen, die als Ergebnis dieses Aufrufs erfolgten, werden durch den Aufruf vonremove()mit denselben Argumenten rückgängig gemacht.z. B.
# if a function was registered like this... @event.listens_for(SomeMappedClass, "before_insert", propagate=True) def my_listener_function(*arg): pass # ... it's removed like this event.remove(SomeMappedClass, "before_insert", my_listener_function)
Oben wurde die Listener-Funktion, die mit
SomeMappedClassverbunden war, auch an Unterklassen vonSomeMappedClassweitergegeben; die Funktionremove()wird all diese Operationen rückgängig machen.Hinweis
Die Funktion
remove()kann nicht gleichzeitig aufgerufen werden, während das Zielereignis ausgeführt wird. Dies hat Auswirkungen auf die Thread-Sicherheit und bedeutet auch, dass ein Ereignis nicht innerhalb der Listener-Funktion für sich selbst entfernt werden kann. Die Liste der auszuführenden Ereignisse befindet sich in einer veränderlichen Sammlung, die während der Iteration nicht geändert werden kann.Ereignisregistrierung und -entfernung sind nicht als "Hochgeschwindigkeitsoperationen" gedacht; sie sind Konfigurationsoperationen. Für Systeme, die sich schnell und in großem Umfang mit Ereignissen verbinden und trennen müssen, verwenden Sie eine veränderliche Struktur, die von einer einzelnen Listener-Funktion aus verwaltet wird.
Siehe auch
- function sqlalchemy.event.contains(target: Any, identifier: str, fn: Callable[[...], Any]) → bool¶
Gibt True zurück, wenn das angegebene Ziel/Identifikator/fn zum Zuhören eingerichtet ist.
Die Designs von flambé! dem Drachen und Der Alchemist wurden von Rotem Yaari erstellt und großzügig gespendet.
Erstellt mit Sphinx 7.2.6. Dokumentation zuletzt generiert: Di 11 Mär 2025 14:40:17 EDT