flask信号

2018-06-18 02:05:58来源:未知 阅读 ()

新老客户大回馈,云服务器低至5折

flask信号

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

  1、信号是什么?

    - 在代码中信号可以理解为在当程序走到一定的位置之后,做指定的操作,flask为我们提供了10个信号

 1 request_started = _signals.signal('request-started')                # 请求到来前执行
 2 request_finished = _signals.signal('request-finished')              # 请求结束后执行
 3  
 4 before_render_template = _signals.signal('before-render-template')  # 模板渲染前执行
 5 template_rendered = _signals.signal('template-rendered')            # 模板渲染后执行
 6  
 7 got_request_exception = _signals.signal('got-request-exception')    # 请求执行出现异常时执行
 8  
 9 request_tearing_down = _signals.signal('request-tearing-down')      # 请求执行完毕后自动执行(无论成功与否)
10 appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 请求上下文执行完毕后自动执行(无论成功与否)
11  
12 appcontext_pushed = _signals.signal('appcontext-pushed')            # 请求上下文push时执行
13 appcontext_popped = _signals.signal('appcontext-popped')            # 请求上下文pop时执行
14 message_flashed = _signals.signal('message-flashed')                # 调用flask在其中添加数据时,自动触发

  2、源码剖析

    执行顺序:

      

 1 before_first_request
 2 触发 request_started 信号
 3 before_request
 4 模板渲染前的信号 before_render_template.send(app, template=template, context=context)
 5 模板渲染
 6 渲染后的信号 template_rendered.send(app, template=template, context=context)
 7 after_request
 8 session.save_session()
 9 触发 request_finished信号
10 如果full_dispatch_request中出错:
11   触发错误处理信号 got_request_exception.send(self, exception=e)
12 触发信号 request_tearing_down

    

    2-1、 request_started 请求到来前执行,在这里我们发现的请求扩展中的before_first_requestbefore_request的源码处理,由此可见request_started的执行顺序为before_first_request之后before_request之前。

    位置: app.__call__ --> app.wsgi_app() --> full_dispatch_request()

 1 def full_dispatch_request(self):
 2 
 3     # before_first_request,这里处理的是否是第一次请求
 4     self.try_trigger_before_first_request_functions()
 5     try:
 6         # 触发request_started信号
 7         request_started.send(self)
 8 
 9         # before_request,处理机制
10         rv = self.preprocess_request()
11         if rv is None:
12             # 执行视图函数
13             rv = self.dispatch_request()
14     except Exception as e:
15         rv = self.handle_user_exception(e)
16     return self.finalize_request(rv)  # 请求结束后执行

    2-2、 request_finished  请求结束后执行,在after_request和保存session之后执行

 1 def finalize_request(self, rv, from_error_handler=False):
 2 
 3     response = self.make_response(rv)
 4     try:
 5         response = self.process_response(response)
 6         # 请求结束后触发
 7         request_finished.send(self, response=response)
 8     except Exception:
 9         if not from_error_handler:
10             raise
11         self.logger.exception('Request finalizing failed with an '
12                               'error while handling an error')
13     return response

    2-3、 got_request_exception   在  full_dispatch_request()  执行出现异常时执行

1 def handle_exception(self, e):
2     exc_type, exc_value, tb = sys.exc_info()
3     # 出错时触发信号
4     got_request_exception.send(self, exception=e)
5     handler = self._find_error_handler(InternalServerError())    

    2-4、 before_render_template  模板渲染之前执行

    入口: render_template() --> _render() 

1 def _render(template, context, app):
2     # 模板渲染之前触发
3     before_render_template.send(app, template=template, context=context)
4     rv = template.render(context)   # 真正的模板渲染
5     # 模板渲染之后触发
6     template_rendered.send(app, template=template, context=context)
7     return rv

    2-5、 template_rendered   模板渲染之后执行(同上)

    2-6、 appcontext_pushed 请求上下文push时执行  

    入口: wsgi_app() --> ctx.push() --> app_ctx.push() 

 

 1 def push(self):
 2 
 3     self._refcnt += 1
 4     if hasattr(sys, 'exc_clear'):
 5         sys.exc_clear()
 6     # _app_ctx_stack是LocalProxy对象,又创建了一个Local对象
 7     _app_ctx_stack.push(self)
 8     # 请求上下文push时执行
 9     appcontext_pushed.send(self.app)
10 
11 def pop(self, exc=_sentinel):
12 
13     try:
14         self._refcnt -= 1
15         if self._refcnt <= 0:
16             if exc is _sentinel:
17                 exc = sys.exc_info()[1]
18             self.app.do_teardown_appcontext(exc) # 两个自动执行信号入口
19     finally:
20         rv = _app_ctx_stack.pop()
21     assert rv is self, 'Popped wrong app context.  (%r instead of %r)' \
22         % (rv, self)
23     # 请求上下文pop时执行
24     appcontext_popped.send(self.app)
25     

    2-7、 appcontext_popped 请求上下文pop时执行(同上)

    2-8、 request_tearing_down 请求结束后自动执行,无论成功与否

    入口:在上面找 self.app.do_teardown_appcontext(exc)  

 1 def do_teardown_request(self, exc=_sentinel):
 2 
 3     if exc is _sentinel:
 4         exc = sys.exc_info()[1]
 5     funcs = reversed(self.teardown_request_funcs.get(None, ()))
 6     bp = _request_ctx_stack.top.request.blueprint
 7     if bp is not None and bp in self.teardown_request_funcs:
 8         funcs = chain(funcs, reversed(self.teardown_request_funcs[bp]))
 9     for func in funcs:
10         func(exc)
11     # 请求完毕自动执行
12     request_tearing_down.send(self, exc=exc)
13 
14 def do_teardown_appcontext(self, exc=_sentinel):
15 
16     if exc is _sentinel:
17         exc = sys.exc_info()[1]
18     for func in reversed(self.teardown_appcontext_funcs):
19         func(exc)
20     # 请求上下文完毕自动执行
21     appcontext_tearing_down.send(self, exc=exc)

    2-9、 appcontext_tearing_down 请求上下文完毕后自动执行,无论成功与否(同上)

    2-10、 message_flashed  在flashed中添加数据时自动执行(入口:flash)

1 def flash(message, category='message'):
2    
3     flashes = session.get('_flashes', [])
4     flashes.append((category, message))
5     session['_flashes'] = flashes
6     # 调用flask在其中添加数据时,自动触发
7     message_flashed.send(current_app._get_current_object(),
8                          message=message, category=category)

 

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:编程语言的分类

下一篇:举例子来说明Python引用和对象