大白话来说,类似于两方属于敌对关系时,某人在敌对方阵营进行交谈,一旦遇到特殊情况,某人便会发送信号,他的同伙接收(监听)到他发的信号后,同伙便会做出一系列的应对策略(进攻|撤
退)。
flask中的信号使用的是一个第三方插件,叫做blinker。通过pip list看一下,如果没有安装,通过以下命令即可安装blinker。
pip install blinker
自定义信号可分为3步来完成。
第一是创建一个信号,第二是监听一个信号,第三是发送一个信号。
以下将对这三步进行讲解:
创建信号:定义信号需要使用到blinker这个包的Namespace类来创建一个命名空间。比如定义一个在访问了某个视图函数的时候的信号。
# Namespace的作用:为了防止多人开发的时候,信号名字冲突的问题
from blinker import Namespace
mysignal = Namespace()
signal1 = mysignal.signal('信号名称')
监听信号:监听信号使用signal1对象的connect方法,在这个方法中需要传递一个函数,用来监听到这个信号后做该做的事情。
def func1(sender,uname):
print(sender)
print(uname)
signal1.connect(func1)
发送信号:发送信号使用signal1对象的send方法,这个方法可以传递一些其他参数过去。
signal1.send(uname='momo')
示例代码:
from flask import Flask
from blinker import Namespace
app = Flask(__name__)
# 信号机制 3步走
# 1.定义信号
signal_space = Namespace()
signal_name = signal_space.signal('访问首页')
# 2.监听信号
def main_func(sender):
print(sender)
print('start main_func')
signal_name.connect(main_func)
# # 3.发送一个信号
# signal_name.send()
@app.route('/')
def index():
print('执行index函数!')
# 3.发送一个信号
signal_name.send()
return "hello world!"
if __name__ == '__main__':
app.run(debug=True)
运行结果:
描述:
定义一个登录的信号,以后用户登录进来以后就发送一个登录信号,然后能够监听这个信号。在监听到这个信号以后,就记录当前这个用户登录的信息用信号的方式,记录用户的登录信息即登录日志。
编写一个signals.py文件创建登录信号:
from blinker import Namespace
from datetime import datetime
from flask import request, g
name_space = Namespace()
# 创建登录信息
login_signal = name_space.signal('login')
def login_log(sender):
now = datetime.now()
ip = request.remote_addr
log_data = f'{g.name}*{now}*{ip}'
# with open('./data/login_log.txt', 'a', encoding='utf-8') as f:
# f.write(log_data + '\n')
# f.close()
print(log_data)
# 监听信号
login_signal.connect(login_log)
使用信号存储用户登录日志:
from flask import Flask, request, g
from signals import login_signal
app = Flask(__name__)
@app.route('/login/')
def login():
name = request.args.get('name')
if name:
g.name = name
# 发送信号
login_signal.send()
return '登录成功'
else:
return '请输入用户名'
if __name__ == '__main__':
app.run(debug=True)
运行结果:
Flask内置了10个常用的信号:
示例代码:
from flask import Flask, render_template, template_rendered
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
def render_func(sender, template, context):
print(sender)
print(template)
print(context)
template_rendered.connect(render_func)
if __name__ == '__main__':
app.run(debug=True)
运行结果:
示例代码:
from flask import Flask, render_template, got_request_exception
app = Flask(__name__)
@app.route('/')
def index():
1 / 0
return render_template('index.html')
# 内置信号
# got_request_exception:在请求过程中抛出异常时发送信号,异常本身会通过exception传递到订阅(监听)的函数中。
# 一般可以监听这个信号,来记录网站异常信息。
def request_exception_log(sender, *args, **kwargs):
print(sender)
print(args)
print(kwargs)
# def request_exception_log2(sender, exception):
# print(sender)
# print(exception)
got_request_exception.connect(request_exception_log)
if __name__ == '__main__':
app.run(debug=True)
运行结果: