信号
信号
一 信号是什么
# 1 Flask框架中的信号基于blinker,其主要就是让开发者可以在flask请求过程中定制一些用户行为
# 2 信号是典型的 观察者模式
-触发某个事执行【模板准备渲染】
-绑定信号:可以绑定多个
只要模板准备渲染--》就会执行这几个绑定的新--》函数
# 3 面向切面编程(AOP)--》一种方案
-整个程序正常运行,但是我们可以把一部分代码,插入到某个位置执行
-钩子函数:只要写了,程序走到哪,就会执行,没写,就不会执行
-序列化类的校验
# 4 通过信号可以做什么事?
-在框架整个执行过程中,插入一些代码执行
比如:记录某个页面的访问量
比如:每次渲染 login.html --->都记录日志
比如:程序出异常---》记录日志
比如:用户表中有个用户创建--》给这个用户发点短信
比如:用户下了订单---》发个邮件通知,让它尽快付款
比如:轮播图表只要发生变化,就删缓存:django中内置信号
二 flask中信号的使用
request_started = _signals.signal('request-started') # 请求到来前执行
request_finished = _signals.signal('request-finished') # 请求结束后执行
before_render_template = _signals.signal('before-render-template') # 模板渲染前执行
template_rendered = _signals.signal('template-rendered') # 模板渲染后执行
got_request_exception = _signals.signal('got-request-exception') # 请求执行出现异常时执行
request_tearing_down = _signals.signal('request-tearing-down') # 请求执行完毕后自动执行(无论成功与否)
appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 应用上下文执行完毕后自动执行(无论成功与否)
appcontext_pushed = _signals.signal('appcontext-pushed') # 应用上下文push时执行
appcontext_popped = _signals.signal('appcontext-popped') # 应用上下文pop时执行
message_flashed = _signals.signal('message-flashed') # 调用flask在其中添加数据时,自动触发
1 内置信号的使用
使用步骤:
-
写一个函数
def func1(*args,**kwargs): print('模板渲染了') print(args) print(kwargs.get('template').name)
-
跟内置信号绑定
from flask import signals signals.before_render_template.connect(func1)
-
等待触发(自动)
2 自定义信号
使用步骤:
-
定义一个自定义信号
from flask.signals import _signals create_user = _signals.signal('create_user')
-
写一个函数
def func1(*args, **kwargs): print('自定义信号执行了') print(args) print(kwargs)
-
跟内置信号绑定
create_user.connect(func1)
-
等待触发(手动)
create_user.send()
三 django中信号使用
Model signals
pre_init # django的modal执行其构造方法前,自动触发
post_init # django的modal执行其构造方法后,自动触发
pre_save # django的modal对象保存前,自动触发
post_save # django的modal对象保存后,自动触发
pre_delete # django的modal对象删除前,自动触发
post_delete # django的modal对象删除后,自动触发
m2m_changed # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
class_prepared # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
Management signals
pre_migrate # 执行migrate命令前,自动触发
post_migrate # 执行migrate命令后,自动触发
Request/response signals
request_started # 请求到来前,自动触发
request_finished # 请求结束后,自动触发
got_request_exception # 请求异常后,自动触发
Test signals
setting_changed # 使用test测试修改配置文件时,自动触发
template_rendered # 使用test测试渲染模板时,自动触发
Database Wrappers
connection_created # 创建数据库连接时,自动触发
1 内置信号使用
-
写一个函数
def callBack(sender, **kwargs): # 过滤banner表 :kwargs就有表名 print('对象保存了')
-
跟内置信号绑定
from django.db.models.signals import pre_save post_save.connect(callBack)
-
等待触发(自动的)
绑定方式二,使用装饰器
pre_save
from django.db.models.signals import pre_save
from django.dispatch import receiver
.models import MyModel
@receiver(pre_save, sender=MyModel)
def my_callback(sender, instance, **kwargs):
print("对象创建成功")
print(sender)
print(kwargs)
# sender 是发送信号的模型,这里是 MyModel。
# instance 是即将保存的模型实例。
# **kwargs 接受其他关键字参数。
post_save
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import MyModel
@receiver(post_save, sender=MyModel, dispatch_uid="model_post_save")
def mymodel_post_save(sender, instance, created, **kwargs):
if created:
# 执行某些操作,例如发送通知或更新其他模型
print(f"新建了一个 ApplyRedisText 实例: {instance}")
else:
# 执行某些操作,例如记录修改
print(f"更新了一个 ApplyRedisText 实例: {instance}")
# sender 参数指明发送信号的模型,这里是 MyModel。
# instance 是被保存的模型实例。
# created 是一个布尔值,指示该实例是新创建的还是已经存在的实例被更新。
# **kwargs 接受其他关键字参数。
request_started
from django.core.signals import request_started
from django.dispatch import receiver
@receiver(request_started)
def my_request_started_handler(sender, environ, **kwargs):
# 在请求开始时执行某些操作
print("Request started!")
# 你可以在这里添加更多逻辑,比如记录日志
# logger.info(f"Request started from {environ['REMOTE_ADDR']}")
# sender 是发送信号的对象,一般是 WSGIHandler。
# environ 是 WSGI 环境字典,包含关于请求的信息。
# **kwargs 接受其他关键字参数。
# 可以将信号处理函数放在 signals.py 文件中,并在 apps.py 中的 ready 方法中导入它。
from django.apps import AppConfig
class MyappConfig(AppConfig):
name = 'myapp'
def ready(self):
import myapp.signals # 导入信号处理模块
2 自定义信号
# 1 定义信号(一般创建一个py文件)(toppings,size 是接受的参数)
import django.dispatch
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])
#2 写个函数注册信号
def callback(sender, **kwargs):
print("callback")
print(sender,kwargs)
pizza_done.connect(callback)
# 3 触发信号
from 路径 import pizza_done
pizza_done.send(sender='seven',toppings=123, size=456)
四 用信号的好处
代码侵入性低---》解耦
五 信号和信号量
# 信号:signal
-flask,django中得 观察者模式 --》信号机制
# 信号量:Semaphore
-并发编程中概念
在Python中,信号量(Semaphore)主要用来控制多个线程或进程对共享资源的访问。信号量本质上是一种计数器的锁,它维护一个许可(permit)数量,每次 acquire() 函数被调用时,如果还有剩余的许可,则减少一个,并允许执行;如果没有剩余许可,则阻塞当前线程直到其他线程释放信号量