骚师博客:
信号你就可以这么理解,请求比喻成赛车,请求走的流程就是赛车道,而信号坐落在赛车道上的加油站和维修站,信号注册的函数好比维修站的人,每经过维修站并且维修站里有人就进行维修
信号这里理解:信号决定了在哪个时候执行,注册的函数定义了该怎么做,请求来时触发信号里的函数
对于信号,你看完后你会觉得,感觉和之前的请求扩展没啥区别样的,但是了解好它的执行先后顺序,对以后进行开放封闭式开发是有益处的,所以我们需要稍稍了解一下其中的源码
触发信号: signals.request_started.send() , 找这个就好了
from flask import Flask,signals,render_templateapp = Flask(__name__)# 往信号中注册函数def func(*args,**kwargs): print('触发型号',args,kwargs)signals.request_started.connect(func)# 触发信号: signals.request_started.send()@app.before_first_requestdef before_first1(*args,**kwargs): pass@app.before_first_requestdef before_first2(*args,**kwargs): pass@app.before_requestdef before_first3(*args,**kwargs): pass@app.route('/',methods=['GET',"POST"])def index(): print('视图') return render_template('index.html')if __name__ == '__main__': app.wsgi_app app.run()
我们还看到flask最核心的这段代码
ctx = self.request_context(environ) ctx.push() error = None try: try: response = self.full_dispatch_request() except Exception as e: error = e response = self.handle_exception(e) except: error = sys.exc_info()[1] raise return response(environ, start_response) finally: if self.should_ignore_error(error): error = None ctx.auto_pop(error)
其中前面几句里的执行没发现send,直接看到full_dispatch_request
#执行before_first_request self.try_trigger_before_first_request_functions() #使用标志位实现,请求过程@app.before_first_request把函数添加到列表中 try: #触发request_started信号 request_started.send(self) #调用before_request rv = self.preprocess_request() if rv is None: #没有返回值继续执行 ''' #执行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) ''' #执行视图函数 rv = self.dispatch_request() except Exception as e: rv = self.handle_user_exception(e) #对返回值做进一步处理 return self.finalize_request(rv)
并且在finalize_request中
response = self.make_response(rv) try: #处理after_request #session.save response = self.process_response(response) #触发request_finished信号 request_finished.send(self, response=response) except Exception: if not from_error_handler: raise self.logger.exception('Request finalizing failed with an ' 'error while handling an error') return response
所以在full_dispatch_request里的触发顺序为
-
执行before_first_request
- 触发request_started信号
-
执行before_request
- 执行before_render_template 渲染前信号(存在模板渲染才执行)
-
模板渲染
- 执行template_rendered 渲染后信号
-
执行视图函数
- 处理after_request
-
session.save
-
触发request_finished信号
下一句代码中,response = self.handle_exception(e),上述10步骤中,任何一步出错,触发错误处理got_request_exception信号
exc_type, exc_value, tb = sys.exc_info() got_request_exception.send(self, exception=e) handler = self._find_error_handler(InternalServerError())
最后在ctx.auto_pop(error)中,一直往下找,有这么一个方法,方法里会触发request_tearing_down信号,表示无论成功与否,都会执行
所以最后还会走 执行request_tearing_down信号