События

SQLAlchemy включает в себя API событий, который публикует широкий спектр крючков во внутренние компоненты как SQLAlchemy Core, так и ORM.

Регистрация мероприятия

Подписка на событие происходит через одну точку API, функцию listen() или декоратор listens_for(). Эти функции принимают цель, строковый идентификатор, который идентифицирует событие, подлежащее перехвату, и определяемую пользователем функцию прослушивания. Дополнительные позиционные и ключевые аргументы этих двух функций могут поддерживаться определенными типами событий, которые могут определять альтернативные интерфейсы для данной функции события или предоставлять инструкции относительно вторичных целей события на основе данной цели.

Имя события и сигнатура аргументов соответствующей функции слушателя выводится из метода спецификации, связанного с классом, который существует в привязке к классу маркера, описанному в документации. Например, документация для PoolEvents.connect() указывает, что имя события "connect" и что определяемая пользователем функция слушателя должна принимать два позиционных аргумента:

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)

Для прослушивания с декоратором listens_for() выглядит так:

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)

Стили именованных аргументов

Существует несколько разновидностей стилей аргументов, которые могут принимать функции-слушатели. На примере PoolEvents.connect() эта функция документирована как принимающая аргументы dbapi_connection и connection_record. Мы можем принять эти аргументы по имени, создав функцию-слушатель, принимающую аргументы **keyword, передав named=True в listen() или listens_for():

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"])

При использовании передачи именованных аргументов имена, перечисленные в спецификации аргументов функции, будут использоваться в качестве ключей в словаре.

Именованный стиль передает все аргументы по имени, независимо от сигнатуры функции, поэтому конкретные аргументы также могут быть перечислены в любом порядке, лишь бы имена совпадали:

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"])

Выше, наличие **kw говорит listens_for(), что аргументы должны передаваться в функцию по имени, а не позиционно.

Цели

Функция listen() очень гибкая в отношении целей. Обычно она принимает классы, экземпляры этих классов, а также связанные классы или объекты, из которых может быть получена соответствующая цель. Например, вышеупомянутое событие "connect" принимает классы и объекты Engine, а также классы и объекты Pool:

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)

Модификаторы

Некоторые слушатели позволяют передавать модификаторы в listen(). Эти модификаторы иногда обеспечивают альтернативные сигнатуры вызова для слушателей. Например, в событиях ORM некоторые слушатели событий могут иметь возвращаемое значение, которое изменяет последующую обработку. По умолчанию ни один слушатель никогда не требует возвращаемого значения, но, передав retval=True, это значение можно поддержать:

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)

Ссылка на событие

Как SQLAlchemy Core, так и SQLAlchemy ORM имеют широкий спектр крючков событий:

  • Основные события - они описаны в Основные мероприятия и включают крючки событий, специфичных для жизненного цикла пула соединений, выполнения операторов SQL, жизненного цикла транзакции, создания и разрушения схемы.

  • ORM Events - они описаны в События ОРМ, и включают в себя крючки событий, специфичные для инструментов класса и атрибутов, крючки инициализации объектов, крючки изменения атрибутов, крючки состояния сессии, смыва и фиксации, крючки инициализации маппера, регистрации объектов/результатов, и крючки персистентности для каждого экземпляра.

Справочник по API

Object Name Description

contains(target, identifier, fn)

Возвращает True, если данная цель/идент/fn настроена на прослушивание.

listen(target, identifier, fn, *args, **kw)

Регистрация функции слушателя для заданной цели.

listens_for(target, identifier, *args, **kw)

Украсить функцию в качестве слушателя для заданной цели + идентификатор.

remove(target, identifier, fn)

Удаление слушателя события.

function sqlalchemy.event.listen(target: Any, identifier: str, fn: Callable[[...], Any], *args: Any, **kw: Any) None

Регистрация функции слушателя для заданной цели.

Функция listen() является частью основного интерфейса для системы событий SQLAlchemy, документированного в События.

например:

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)
Параметры:
  • insert (bool) – Поведение по умолчанию для обработчиков событий заключается в добавлении декорированной функции, определенной пользователем, во внутренний список зарегистрированных слушателей событий при обнаружении. Если пользователь регистрирует функцию с помощью insert=True, SQLAlchemy будет вставлять (добавлять) функцию во внутренний список при обнаружении. Эта функция обычно не используется и не рекомендуется сопровождающими SQLAlchemy, но предоставляется для того, чтобы определенные функции, определенные пользователем, могли запускаться раньше других, например, при Changing the sql_mode in MySQL.

  • named (bool) – При использовании передачи именованных аргументов имена, перечисленные в спецификации аргументов функции, будут использоваться в качестве ключей в словаре. См. Стили именованных аргументов.

  • once (bool) – Использование частного/внутреннего API. Утратил силу. Этот параметр обеспечивает, что функция события будет выполняться только один раз для данной цели. Однако он не подразумевает автоматической отмены регистрации функции слушателя; ассоциирование произвольно большого числа слушателей без их явного удаления приведет к неограниченному росту памяти, даже если указано once=True.

  • propagate (bool) – Карга propagate доступна при работе с инструментарием ORM и событиями отображения. Примеры см. в MapperEvents и MapperEvents.before_mapper_configured().

  • retval (bool) – Этот флаг применяется только к определенным слушателям событий, каждый из которых включает документацию, объясняющую, когда его следует использовать. По умолчанию ни один слушатель никогда не требует возвращаемого значения. Однако некоторые слушатели поддерживают специальное поведение для возвращаемых значений и указывают в своей документации, что флаг retval=True необходим для обработки возвращаемого значения. К наборам слушателей событий, использующих listen.retval, относятся ConnectionEvents и AttributeEvents.

Примечание

Функция listen() не может быть вызвана одновременно с выполнением целевого события. Это имеет значение для безопасности потоков, а также означает, что событие не может быть добавлено изнутри функции слушателя для самого себя. Список запускаемых событий находится внутри мутабельной коллекции, которая не может быть изменена во время итерации.

Регистрация и удаление событий не является операцией «высокой скорости»; это конфигурационная операция. Для систем, которым необходимо быстро ассоциировать и деассоциировать с событиями в больших масштабах, используйте изменяемую структуру, которая обрабатывается внутри одного слушателя.

См.также

listens_for()

remove()

function sqlalchemy.event.listens_for(target: Any, identifier: str, *args: Any, **kw: Any) Callable[[Callable[[...], Any]], Callable[[...], Any]]

Украсить функцию в качестве слушателя для заданной цели + идентификатор.

Декоратор listens_for() является частью основного интерфейса для системы событий SQLAlchemy, документированного в События.

Эта функция обычно имеет те же kwargs, что и listens().

например:

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
    )

Данная функция также может быть вызвана только для первого вызова события с помощью аргумента once:

@event.listens_for(Mapper, "before_configure", once=True)
def on_config():
    do_config()

Предупреждение

Аргумент once не подразумевает автоматической отмены регистрации функции слушателя после ее первого вызова; запись слушателя останется связанной с целевым объектом. Ассоциирование произвольно большого числа слушателей без их явного удаления приведет к неограниченному росту памяти, даже если указано once=True.

См.также

listen() - общее описание прослушивания события

function sqlalchemy.event.remove(target: Any, identifier: str, fn: Callable[[...], Any]) None

Удаление слушателя события.

Аргументы здесь должны точно соответствовать тем, которые были отправлены в listen(); вся регистрация событий, которая произошла в результате этого вызова, будет отменена вызовом remove() с теми же аргументами.

например:

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

Выше функция слушателя, связанная с SomeMappedClass, также распространялась на подклассы SomeMappedClass; функция remove() вернет все эти операции.

Примечание

Функция remove() не может быть вызвана одновременно с выполнением целевого события. Это имеет значение для безопасности потоков, а также означает, что событие не может быть удалено внутри функции слушателя для самого себя. Список запускаемых событий находится внутри мутабельной коллекции, которая не может быть изменена во время итерации.

Регистрация и удаление событий не является операцией «высокой скорости»; это конфигурационная операция. Для систем, которым необходимо быстро ассоциировать и деассоциировать с событиями в больших масштабах, используйте изменяемую структуру, которая обрабатывается внутри одного слушателя.

См.также

listen()

function sqlalchemy.event.contains(target: Any, identifier: str, fn: Callable[[...], Any]) bool

Возвращает True, если данная цель/идент/fn настроена на прослушивание.

Вернуться на верх