Flask框架中的信号基于blinker,其主要就是让开发者可是在flask请求过程中定制一些用户行为。

pip3 install blinker

1.内置信号

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在其中添加数据时,自动触发
signals.py
# -*- coding: utf-8 -*-
"""
flask.signals
~~~~~~~~~~~~~ Implements signals based on blinker if available, otherwise
falls silently back to a noop. :copyright: (c) 2015 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
signals_available = False
try:
from blinker import Namespace
signals_available = True
except ImportError:
class Namespace(object):
def signal(self, name, doc=None):
return _FakeSignal(name, doc) class _FakeSignal(object):
"""If blinker is unavailable, create a fake class with the same
interface that allows sending of signals but will fail with an
error on anything else. Instead of doing anything on send, it
will just ignore the arguments and do nothing instead.
""" def __init__(self, name, doc=None):
self.name = name
self.__doc__ = doc
def _fail(self, *args, **kwargs):
raise RuntimeError('signalling support is unavailable '
'because the blinker library is '
'not installed.')
send = lambda *a, **kw: None
connect = disconnect = has_receivers_for = receivers_for = \
temporarily_connected_to = connected_to = _fail
del _fail # The namespace for code signals. If you are not Flask code, do
# not put signals in here. Create your own namespace instead.
_signals = Namespace() # Core signals. For usage examples grep the source code or consult
# the API documentation in docs/api.rst as well as docs/signals.rst
template_rendered = _signals.signal('template-rendered')
before_render_template = _signals.signal('before-render-template')
request_started = _signals.signal('request-started')
request_finished = _signals.signal('request-finished')
request_tearing_down = _signals.signal('request-tearing-down')
got_request_exception = _signals.signal('got-request-exception')
appcontext_tearing_down = _signals.signal('appcontext-tearing-down')
appcontext_pushed = _signals.signal('appcontext-pushed')
appcontext_popped = _signals.signal('appcontext-popped')
message_flashed = _signals.signal('message-flashed')

源码示例

request_started
class Flask(_PackageBoundObject):

    def full_dispatch_request(self):

        self.try_trigger_before_first_request_functions()
try:
# ############### 触发request_started 信号 ###############
request_started.send(self)
rv = self.preprocess_request()
if rv is None:
rv = self.dispatch_request()
except Exception as e:
rv = self.handle_user_exception(e)
response = self.make_response(rv)
response = self.process_response(response) # ############### request_finished 信号 ###############
request_finished.send(self, response=response)
return response def wsgi_app(self, environ, start_response): ctx = self.request_context(environ)
ctx.push()
error = None
try:
try:
response = self.full_dispatch_request()
except Exception as e:
error = e
response = self.make_response(self.handle_exception(e))
return response(environ, start_response)
finally:
if self.should_ignore_error(error):
error = None
ctx.auto_pop(error)
request_finished

同上

before_render_template
def render_template(template_name_or_list, **context):
"""Renders a template from the template folder with the given
context. :param template_name_or_list: the name of the template to be
rendered, or an iterable with template names
the first one existing will be rendered
:param context: the variables that should be available in the
context of the template.
"""
ctx = _app_ctx_stack.top
ctx.app.update_template_context(context)
return _render(ctx.app.jinja_env.get_or_select_template(template_name_or_list),
context, ctx.app) def _render(template, context, app):
"""Renders the template and fires the signal""" # ############### before_render_template 信号 ###############
before_render_template.send(app, template=template, context=context)
rv = template.render(context) # ############### template_rendered 信号 ###############
template_rendered.send(app, template=template, context=context)
return rv
template_rendered

同上

got_request_exception
class Flask(_PackageBoundObject):

    def handle_exception(self, e):

        exc_type, exc_value, tb = sys.exc_info()

        # ############### got_request_exception 信号 ###############
got_request_exception.send(self, exception=e)
handler = self._find_error_handler(InternalServerError()) if self.propagate_exceptions:
# if we want to repropagate the exception, we can attempt to
# raise it with the whole traceback in case we can do that
# (the function was actually called from the except part)
# otherwise, we just raise the error again
if exc_value is e:
reraise(exc_type, exc_value, tb)
else:
raise e self.log_exception((exc_type, exc_value, tb))
if handler is None:
return InternalServerError()
return handler(e) def wsgi_app(self, environ, start_response): ctx = self.request_context(environ)
ctx.push()
error = None
try:
try:
response = self.full_dispatch_request()
except Exception as e:
error = e
# 这里这里这里这里这里这里这里这里这里这里这里这里 #
response = self.make_response(self.handle_exception(e))
return response(environ, start_response)
finally:
if self.should_ignore_error(error):
error = None
ctx.auto_pop(error)
request_tearing_down
class AppContext(object):
def push(self):
"""Binds the app context to the current context."""
self._refcnt += 1
if hasattr(sys, 'exc_clear'):
sys.exc_clear()
_app_ctx_stack.push(self)
# ############## 触发 appcontext_pushed 信号 ##############
appcontext_pushed.send(self.app) def pop(self, exc=_sentinel):
"""Pops the app context."""
try:
self._refcnt -= 1
if self._refcnt <= 0:
if exc is _sentinel:
exc = sys.exc_info()[1]
# ############## 触发 appcontext_tearing_down 信号 ##############
self.app.do_teardown_appcontext(exc)
finally:
rv = _app_ctx_stack.pop()
assert rv is self, 'Popped wrong app context. (%r instead of %r)' \
% (rv, self) # ############## 触发 appcontext_popped 信号 ##############
appcontext_popped.send(self.app) class RequestContext(object):
def push(self):
top = _request_ctx_stack.top
if top is not None and top.preserved:
top.pop(top._preserved_exc) app_ctx = _app_ctx_stack.top
if app_ctx is None or app_ctx.app != self.app: # ####################################################
app_ctx = self.app.app_context()
app_ctx.push()
self._implicit_app_ctx_stack.append(app_ctx)
else:
self._implicit_app_ctx_stack.append(None) if hasattr(sys, 'exc_clear'):
sys.exc_clear() _request_ctx_stack.push(self) # Open the session at the moment that the request context is
# available. This allows a custom open_session method to use the
# request context (e.g. code that access database information
# stored on `g` instead of the appcontext).
self.session = self.app.open_session(self.request)
if self.session is None:
self.session = self.app.make_null_session() class Flask(_PackageBoundObject): def wsgi_app(self, environ, start_response): ctx = self.request_context(environ)
ctx.push()
error = None
try:
try:
response = self.full_dispatch_request()
except Exception as e:
error = e
response = self.make_response(self.handle_exception(e))
return response(environ, start_response)
finally:
if self.should_ignore_error(error):
error = None
ctx.auto_pop(error) def pop(self, exc=_sentinel):
app_ctx = self._implicit_app_ctx_stack.pop() try:
clear_request = False
if not self._implicit_app_ctx_stack:
self.preserved = False
self._preserved_exc = None
if exc is _sentinel:
exc = sys.exc_info()[1] # ################## 触发 request_tearing_down 信号 ##################
self.app.do_teardown_request(exc) # If this interpreter supports clearing the exception information
# we do that now. This will only go into effect on Python 2.x,
# on 3.x it disappears automatically at the end of the exception
# stack.
if hasattr(sys, 'exc_clear'):
sys.exc_clear() request_close = getattr(self.request, 'close', None)
if request_close is not None:
request_close()
clear_request = True
finally:
rv = _request_ctx_stack.pop() # get rid of circular dependencies at the end of the request
# so that we don't require the GC to be active.
if clear_request:
rv.request.environ['werkzeug.request'] = None # Get rid of the app as well if necessary.
if app_ctx is not None:
# ####################################################
app_ctx.pop(exc) assert rv is self, 'Popped wrong request context. ' \
'(%r instead of %r)' % (rv, self) def auto_pop(self, exc):
if self.request.environ.get('flask._preserve_context') or \
(exc is not None and self.app.preserve_context_on_exception):
self.preserved = True
self._preserved_exc = exc
else:
self.pop(exc)
appcontext_tearing_down

同上

appcontext_pushed

同上

appcontext_popped

同上

message_flashed
def flash(message, category='message'):
"""Flashes a message to the next request. In order to remove the
flashed message from the session and to display it to the user,
the template has to call :func:`get_flashed_messages`. .. versionchanged:: 0.3
`category` parameter added. :param message: the message to be flashed.
:param category: the category for the message. The following values
are recommended: ``'message'`` for any kind of message,
``'error'`` for errors, ``'info'`` for information
messages and ``'warning'`` for warnings. However any
kind of string can be used as category.
"""
# Original implementation:
#
# session.setdefault('_flashes', []).append((category, message))
#
# This assumed that changes made to mutable structures in the session are
# are always in sync with the session object, which is not true for session
# implementations that use external storage for keeping their keys/values.
flashes = session.get('_flashes', [])
flashes.append((category, message))
session['_flashes'] = flashes # ############### 触发 message_flashed 信号 ###############
message_flashed.send(current_app._get_current_object(),
message=message, category=category)

2.自定义信号

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask, current_app, flash, render_template
from flask.signals import _signals app = Flask(import_name=__name__) # 自定义信号
xxxxx = _signals.signal('xxxxx') def func(sender, *args, **kwargs):
print(sender) # 自定义信号中注册函数
xxxxx.connect(func) @app.route("/x")
def index():
# 触发信号
xxxxx.send('123123', k1='v1')
return 'Index' if __name__ == '__main__':
app.run()

flask blinker信号的更多相关文章

  1. Inside Flask - signal 信号机制

    Inside Flask - signal 信号机制 singal 在平常的 flask web 开发过程中较少接触到,但对于使用 flask 进行框架级别的开发时,则必须了解相关的工作机制.flas ...

  2. Django 的信号 & Flask 的信号

    信号:框架内部已帮助开发者预留的可扩展的位置 一.Django 的信号 项目目录结构: django_signal |--- app01 |--- models.py |--- views.py .. ...

  3. flask使用blinker信号机制解耦业务代码解决ImportError: cannot import name 'app',以异步发送邮件为例

    百度了大半天,不知道怎么搞,直到学习了blinker才想到解决办法,因为之前写java都是文件分开的, 所以发送邮件业务代码也放到view里面,但是异步线程需要使用app,蛋疼的是其他模块不能从app ...

  4. 5、flask之信号和mateclass元类

    本篇导航: flask实例化参数 信号 metaclass元类解析 一.flask实例化参数 instance_path和instance_relative_config是配合来用的:这两个参数是用来 ...

  5. flask之信号和mateclass元类

    本篇导航: flask实例化参数 信号 metaclass元类解析 一.flask实例化参数 instance_path和instance_relative_config是配合来用的:这两个参数是用来 ...

  6. flask框架----信号

    一.实例化补充 instance_path和instance_relative_config是配合来用的.这两个参数是用来找配置文件的,当用app.config.from_pyfile('settin ...

  7. flask之信号

    Flask框架中的信号基于blinker,其主要就是让开发者可是在flask请求过程中定制一些用户行为. pip3 install blinker 1. 内置信号 request_started = ...

  8. 【Flask】Flask常用信号

    使用信号分为3步,第一是定义一个信号,第二是监听一个信号,第三是发送一个信号. 1. 定义信号:定义信号需要使用到blinker这个包的Namespace类来创建一个命名空间.比如定义一个在访问了某个 ...

  9. flask的信号使用

    from blinker import Namespace from datetime import datetime from flask import request namespace = Na ...

  10. Inside Flask - flask.__init__.py 和核心组件

    Inside Flask - flask.__init__.py 和核心组件 简单的示例 首先看看一个简单的示例.使用 Flask ,通常是从 flask 模块导入 Flask . request 等 ...

随机推荐

  1. DevEco Device Tool 3.1 Release新版本发布,新增资源管理器、SFTP、HDC

     原文链接:https://mp.weixin.qq.com/s/UGBirjf8nBjnfKck9TlyWg,点击链接查看更多技术内容:   DevEco Device Tool是面向智能设备开发者 ...

  2. Centos 8.0 minimal命令行安装图形化界面(超详细)

    Centos 8.0 安装图形化界面(超详细) 开始之前呢,请先查看您的Centos版本和是否有root账户权限. 一.安装Centos 图形化界面并重启 下载安装图形化界面 执行命令 yum gro ...

  3. mysql 重新整理——sql 执行语句的顺序[五]

    前言 盗图: 其实在复杂的语句中,需要我们逐步去分析,然后呢,我们了解一些优化器到底是如何帮我们优化的,就知道到底是mysql怎么执行代码. 我把以前的丢了,后续补全.

  4. This beta version of Typora is expired, please download and install a newer version. 实测最简单有效的方案

    This beta version of Typora is expired, please download and install a newer version. 实测最简单有效的方案 一.问题 ...

  5. 将项目封装进docker进行迁移和使用

    首先要理解docker的基本使用,本文不做过多阐述,博主也对docker没有了解透彻. 这里列一下docker的基本命令: docker info # 查看docker信息 docker -v # 查 ...

  6. ImportError: Cannot load backend 'TkAgg' which requires the 'tk' interactive framework, as 'headless' is currently running

    MMdetection多卡训练常遇到的两个错误,百度无果,没解决,去github里mmdetection的issue模块搜索了一下找到正解. 这里记录一下,方便后者. 1️⃣ ImportError: ...

  7. 使用日志上下文聚合插件使能上下文查询及Livetail

    简介: 日志上下文浏览是排查业务故障时常用的方式,但受限于Logtail插件系统的设计,在Logtail 1.2.1版本前,如果用户使用Logtail插件来处理日志或采集容器的标准输出,那么用户将无法 ...

  8. 阿里云数字化安全生产平台 DPS V1.0 正式发布!

    ​简介:数字化安全生产平台则帮助客户促进业务与 IT 的全面协同,从业务集中监控.业务流程管理.应急指挥响应等多维度来帮助客户建立完善专业的业务连续性保障体系. 作者:银桑.比扬 阿里云创立于 200 ...

  9. StarLake:汇量科技云原生数据湖的探索和实践

    简介: 快速了解汇量科技在云原生数据湖领域的探索和实践,详解 StarLake 的架构及业务应用案例. 作者:陈绪(汇量科技资深算法架构师,EnginePlus 2.0 产品负责人) 内容框架: 互联 ...

  10. [LLM] 开源 AI 大语言模型的本地化定制实践

      LLM(Large Language Model,大型语言模型)是一种基于深度学习的自然语言处理模型,旨在理解和生成人类语言. 它们在大量的文本数据上进行训练,可以执行广泛的任务,包括文本总结.翻 ...