Framework для python Flask - Подписки на сигналы на основе декоратора

Для эффективной работы с событиями и сигналами в приложениях Flask рекомендуется использовать декоратор @app.signal
. Это позволяет быстро и просто подписывать функции на определённые события, не усложняя код и не требуя создания сложной структуры.
Пример: Представьте, что вам нужно выполнить определенный блок кода при изменении статуса заказа. Декоратор позволяет это сделать с помощью минимального синтаксиса:
from flask import Flask
app = Flask(__name__)
@app.signal('order_status_changed')
def order_status_handler(order_id, new_status):
# Логика обработки изменения статуса заказа
print(f"Статус заказа {order_id} изменён на {new_status}")
# ... (остальной код вашего приложения)
Этот подход обеспечивает: чёткую организацию, отсутствие дублей в коде и легкую настраиваемость. Легко обрабатывать события, связанные с другими частями приложения, без значительного усложнения структуры.
Framework для Python Flask - Подписки на сигналы на основе декоратора
Используйте декоратор для регистрации функций-обработчиков на события. Это гарантирует гибкость и организованность, особенно при росте приложения.
Пример структуры:
import functools from flask import Flask app = Flask(__name__) signals = {} def signal(event_name): def decorator(func): if event_name not in signals: signals[event_name] = [] signals[event_name].append(func) return func return decorator @signal("user_created") def handle_user_creation(user): print(f"Пользователь {user} создан.") @signal("user_updated") def handle_user_update(user): print(f"Пользователь {user} обновлен.") @app.route('/create_user', methods=['POST']) def create_user(): # Логика создания пользователя user = 'Новый пользователь' # Важно! Отправка сигнала! for handler in signals.get("user_created", []): handler(user) return 'OK' if __name__ == '__main__': app.run(debug=True)
Ключевые моменты:
- Разделение логики обработки событий (функции `handle_user_creation`, `handle_user_update`) от основной логики (маршрут `/create_user`).
- Использование словаря `signals` для хранения подписчиков на события.
- Декоратор `signal` для регистрации функций-обработчиков. Он добавляет функцию в список обработчиков конкретного события.
- В `create_user` вызываются все обработчики события `user_created`.
- Обратите внимание на важность `signals.get("user_created", [])`, это предотвращает ошибку `KeyError` если нет зарегистрированных обработчиков для данного события.
Этот подход позволяет легко добавлять и удалять обработчики событий без изменения основной части кода, что делает систему более масштабируемой и поддерживаемой.
Установка и импорт необходимого пакета
Для работы с фреймворком Flask и декораторами подписок на сигналы используйте пакет Flask-Signal
.
Инструкция по установке:
Используйте команду pip install flask-signal
в терминале.
Пример импорта:
from flask_signal import Signal
Этот код импортирует необходимый класс Signal
, который позволяет создавать и обрабатывать сигналы.
Создание базовой структуры приложения Flask
Для начала создайте папку проекта и внутри нее файл app.py
.
- Создайте файл
app.py
с кодом ниже
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "Главная страница"
if __name__ == "__main__":
app.run(debug=True)
Этот код импортирует Flask, создаёт приложение Flask с именем app
и определяет маршрут /
. Функция index
возвращает строку "Главная страница". Блок if __name__ == "__main__":
запускает приложение в отладочном режиме.
- Далее, убедитесь, что у вас установлен Flask:
pip install Flask
- Запустите приложение из командной строки в папке проекта:
python app.py
- В браузере перейдите по адресу:
http://127.0.0.1:5000/
Если всё работает, вы увидите "Главная страница".
- Добавьте в проект папку
signals
, с файлами, связанными с подписками
Определение сигналов и декораторов подписки
Для создания подписок на события, используйте декораторы. Они связывают функции с определёнными сигналами.
Сигнал | Декоратор | Описание |
---|---|---|
app.signal_name |
@app.signal_name.connect |
Декоратор подписки на сигнал app.signal_name . Функция, помеченная этим декоратором, будет вызвана при возникновении события. |
Пример сигнала | user_submitted |
|
Пример обработки сигнала | @app.user_submitted.connect |
|
Функция-обработчик |
def handle_submission(user_id, data) # Обработка данных print(f"Данные пользователя {user_id} получены") return True |
Правильная связь достигается назначением функции для работы с данным сигналом.
Сигнал, на который помечается декоратор, должен существовать.
Необходимо использовать корректное имя сигнала.
Подключение обработки событий к сигналам
Для обработки сигнала в Flask-фреймворке, используйте декоратор @app.signal
. Внутри функции, помеченной этим декоратором, используйте ключевые слова аргументов для обозначения данных события. Например:
Пример:
from flask import Flask
app = Flask(__name__)
@app.signal('user_registered')
def register_user_handler(user_data):
print(f"Пользователь {user_data['username']} успешно зарегистрирован.")
# Дополнительные действия, например, отправка email
return True # Возвращаем True, если обработка успешна.
В этом примере, при срабатывании события user_registered
, вызывается функция register_user_handler
. Параметр user_data
содержит информацию о зарегистрированном пользователе. Возвращаемое значение (True
в данном случае) указывает успешную обработку события.
Важно! Сигналы и связанные с ними данные передаются явно. Не предполагайте наличия данных, если они не определены. Определите тип данных, передаваемых в сигнале, и получите доступ к нем через соответствующий параметр в вашем обработчике.
Пример с типом данных:
from flask import Flask
import json
app = Flask(__name__)
@app.signal('order_placed', dict)
def order_placed_handler(order_details):
order_details['status'] = 'processed'
print(f"Заказ обработан: {json.dumps(order_details)}")
return True
Здесь в сигнале order_placed
передаются данные типа dict
. Обработчик получает этот словарь в параметре order_details
, изменяет его и логирует результат. Это показывает как работать с конкретным типом данных.
Обработка сигналов с передачей данных
Для передачи данных при обработке сигналов используйте аргументы декоратора. Это позволяет сделать код более гибким и избежать проблем со связью между обработчиками.
Пример:
import flask from flask_signals import signal app = flask.Flask(__name__) @signal('user_created') def user_created_handler(user_id): print(f"Пользователь с ID {user_id} создан.") # Дополнительная логика, связанная с созданием пользователя return {'success': True} @app.route('/create_user') def create_user(): user_id = 123 signal('user_created').send(user_id) return "Пользователь создан." if __name__ == '__main__': app.run(debug=True)
В этом примере декоратор @signal('user_created')
получает параметр user_id
, который передаётся в обработчик user_created_handler
. Обработчик может использовать эту информацию для выполнения нужной задачи. Обратите внимание на возвращаемое значение функции user_created_handler
– словарь, в котором хранится информация о результате обработки сигнала. Это позволяет организовать более сложный callback.
Можно передавать объекты класса, словари и любые другие типы данных.
При большом количестве данных для передачи используйте сериализацию JSON для упрощения обработки.
Примеры использования подписки на разные сигналы
Подписка на сигналы в Flask позволяет реагировать на события в приложении. Ниже примеры подписки на разные типы сигналов.
Пример 1: Подписка на сигнал изменения статуса заказа:
from flask import Flask
from flask_signals import signal
app = Flask(__name__)
@signal('order_status_changed')
def order_status_changed_handler(order_id, new_status):
print(f'Статус заказа {order_id} изменен на {new_status}')
#код, который генерирует сигнал
@app.route('/order//status/')
def change_status(order_id, new_status):
order_status_changed.send(app, order_id=order_id, new_status=new_status)
return 'Статус изменен'
if __name__ == '__main__':
app.run(debug=True)
Функция order_status_changed_handler
обрабатывает сигнал order_status_changed
, получая идентификатор заказа и новый статус. Маршрут проверяет статус и генерирует сигнал.
Пример 2: Подписка на сигнал сброса данных:
@signal('data_reset')
def data_reset_handler():
try:
# Обработка сброса данных
print("Данные сброшены")
except Exception as e:
print(f"Ошибка при сбросе данных: {e}")
# код, который генерирует сигнал reset
@app.route('/reset_data')
def reset_data():
data_reset.send(app)
return 'Данные сброшены'
Обработка ошибки включена для практичности. Сигнал обработан без дополнительных параметров.
Пример 3: Подписка на сигнал при регистрации нового пользователя:
@signal('user_registered')
def user_registered_handler(user_id, username):
print(f'Пользователь {username} (ID: {user_id}) успешно зарегистрирован')
#код, который генерирует сигнал
def create_user(user_id, username):
user_registered.send(app, user_id=user_id, username=username)
Этот пример показывает обработку сигнала с данными о зарегистрированном пользователе (ID, имя пользователя).