flask中的信号机制

flask中信号机制

Flask信号允许特定的发送端通知订阅者发生了什么。既然知道发生了什么,那我们可以知道接下来该做什么了。Flask提供了一些信号(核心信号),其他扩展则提供了更多的信号。信号是用于通知订阅者,而不是应该鼓励订阅者修改数据。信号依赖于Blinker库,因此需要确保该库已经安装。信号处理器是无序执行的,并且不修改任何数据,主要用于记录事件(比如记录日志)。

创建信号:

如果你要在自己的应用中使用信号,你可以直接使用Blinker库。最常见的使用情况是命名一个自定义的Namespace的信号。这也是大多数时候推荐的做法。

代码如下: 

from blinker import Namespace
my_signals=Namespace()
model_saved=my_signals.signal('model-saved')

signal是Namespace类的函数,其原型是:signal(self,name,doc=None)  返回一个信号对象。其实name参数是信号对象的名字,可以用name属性来访问信号名:model_saved.name。至此,信号已经创建好。

发送信号:

发送信号,可以通过调用send()方法来进行。send()函数原型是:send(self,*sender,**kwargs)。其中,sender是发送者,kwargs是可选参数。

代码如下:

class Model(object):
    ......
    def save(self):
        model_saved.send(self)

永远尝试选择一个合适的发送者。如果你有一个发出信号的类,把self作为发送者。如果你从一个随机的函数发出信号,把current_app._get_current_object()作为发送者。(不要把current_app作为发送者传递给信号。请使用current_app._get_current_object()。因为current_app是一个代理。不是实际的应用对象。)

订阅信号:

使用信号的connect()方法可以订阅该信号。该方法的原型是:connect(receiver,sender=ANY,weak=True)

   receiver:信号发出时要调用的函数。

   sender:该参数是可选的,用于确定信号的发送者。所有核心Flask信号的发送者是应用本身。因此当订阅信号时请指定发送者,除非你真的想要收听应用的所有信号。当你在开发一个扩展时,尤其要注意这点。

   weak:如果是True,那么信号与接收者之间是弱引用。当接收者超出范围或被垃圾回收时,信号与接收者自动断开连接。

也可以使用disconnect()方法来退订信号。该方法原型为:disconnect(receiver,sender=ANY)

其中:receiver为先前connect()函数的第一个参数receiver。sender为信号的发送者。

信号订阅装饰器:

Blinker 1.1版本中还可以用connect_via()装饰器轻松订阅信号:

from flask import template_renderd

@template_rendered.connect_via(app)

def when_template_rendered(sender,template,context,**extra):

    print 'Template %s is rendered with %s' %(template.name,context)

核心信号:

Flask 中有以下信号:

  • flask.template_rendered

  • 这个信号发送于一个模板被渲染成功后。信号传递的template是模板的实例,context是环境对象是一个字典。

    订阅示例:

    def log_template_renders(sender, template, context, **extra):
        sender.logger.debug('Rendering template "%s" with context %s',
                            template.name or 'string template',
                            context)
  • from flask import template_rendered
  • template_rendered.connect(log_template_renders, app)
  • flask.request_started

  • 这个信号发送于请求开始之前,且请求环境设置完成之后。因为请求环境已经绑定, 所以订阅者可以用标准的全局代理,如 request 来操作请求。

    订阅示例:

    def log_request(sender, **extra):
        sender.logger.debug('Request context is set up')
  • from flask import request_started
  • request_started.connect(log_request, app)
  • flask.request_finished

  • 这个信号发送于向客户端发送响应之前。信号传递的response为将要发送的响应。

    订阅示例:

    def log_response(sender, response, **extra):
        sender.logger.debug('Request context is about to close down.  '
                            'Response: %s', response)
  • from flask import request_finished
  • request_finished.connect(log_response, app)
  • flask.got_request_exception

  • 这个信号发送于请求进行中发生异常的时候。它的发送 早于 标准异常处理介于。 在调试模式下,虽然没有异常处理,但发生异常时也发送这个信号。信号传递的exception是异常对象。

    订阅示例:

    def log_exception(sender, exception, **extra):
        sender.logger.debug('Got exception during processing: %s', exception)
  • from flask import got_request_exception
  • got_request_exception.connect(log_exception, app)
  • flask.request_tearing_down

  • 这个信号发送于请求崩溃的时候,不管是否引发异常。目前,侦听此信号的函数在一般 崩溃处理器后调用,但是没有什么东西可用。

    订阅示例:

    def close_db_connection(sender, **extra):
        session.close()from flask import appcontext_tearing_down
  • request_tearing_down.connect(close_db_connection, app)

    在 Flask 版本 0.9 中,这还会传递一个exc关键字参数,如果这个参数存在的话。 这个参数是引发崩溃的异常的引用。

  • flask.appcontext_tearing_down

  • 当应用环境崩溃时发送这个信号。这个信号总是会发送,甚至是因为一个异常引发的 崩溃。侦听这个信号的函数会在常规崩溃处理器后被调用,但是你无法回馈这个信号。

    订阅示例:

    def close_db_connection(sender, **extra):
        session.close()from flask import request_tearing_down
  • appcontext_tearing_down.connect(close_db_connection, app)

    这还会传递一个exc关键字参数,如果这个参数存在的话。这个参数是引发崩溃的 异常的引用。

  • flask.appcontext_pushed

  • 当一个应用的环境被压入时,应用会发送这个信号。这个信号通常用于在单元测试中 临时钩接信息。例如可以用于改变g对象中现存的资源。

    用法示例:

    from contextlib import contextmanagerfrom
  • flask import appcontext_pushed
  • @contextmanagerdef user_set(app, user):
        def handler(sender, **kwargs):
            g.user = user
        with appcontext_pushed.connected_to(handler, app):
            yield

    在测试代码中这样写:

    def test_user_me(self):
        with user_set(app, 'john'):
            c = app.test_client()
            resp = c.get('/users/me')
            assert resp.data == 'username=john'

    New in version 0.10.

  • appcontext_popped

  • 当一个应用的环境被弹出时,应用会发送这个信号。这个信号通常写成appcontext_tearing_down 信号。

    New in version 0.10.

  • flask.message_flashed

  • 当应用闪现一个消息时会发出这个信号。message`参数是消息内容, `category参数是消息类别。

    订阅示例:

    recorded = []def record(sender, message, category, **extra):
        recorded.append((message, category))
  • from flask import message_flashed
  • message_flashed.connect(record, app)


转载于:https://my.oschina.net/935572630/blog/372241

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值