flask之信号

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)

 

转载于:https://www.cnblogs.com/chitalu/p/8659153.html

### FPGA 中实现对 Flash 信号的捕捉 在FPGA中实现对Flash信号的捕捉主要依赖于硬件描述语言(HDL),如Verilog或VHDL,来定义接口逻辑并控制数据传输过程。通常情况下,为了有效地捕获来自Flash设备的数据流,需要构建专门的状态机用于管理读取周期内的各种操作。 对于具体的实现方法,在初始化阶段应设置好必要的参数,比如时钟分频因子以确保采样频率适合目标外设的工作速率;接着通过发送命令序列启动一次完整的事务处理流程——这可能涉及地址指针定位、指令编码以及实际I/O端口的操作等环节[^1]。 下面给出一段基于Verilog HDL编写的小型状态机示例代码,该模块负责执行简单的SPI Flash读取动作,并将接收到的信息保存到内部寄存器中: ```verilog module spi_flash_capture ( input wire clk, // 主时钟输入 input wire rst_n, // 复位信号(低电平有效) output reg csb, // 片选信号 (active low) output reg sck, // SPI串行时钟线 inout wire mosi, // 主输出/从入 数据线 input wire miso, // 主入/从出 数据线 output reg [7:0] data // 捕获后的单字节数据 ); // 定义有限状态机的状态枚举类型 typedef enum logic [2:0] { IDLE, CMD_SENDING, ADDR_SENDING, DUMMY_CYCLE, DATA_READING } state_t; state_t current_state; state_t next_state; integer bit_cnt; // 记录当前正在传送的bit位置 reg [7:0] cmd_reg; // 存储要发出的命令 reg [23:0] addr_reg; // 地址寄存器 wire ready_to_read_data; // 表明可以开始接收数据标志 assign ready_to_read_data = ((current_state == DATA_READING) && (bit_cnt >= 8)); always @(posedge clk or negedge rst_n) begin : proc_current_state if (!rst_n) current_state <= IDLE; else current_state <= next_state; end always @(*) begin : comb_next_state_logic case(current_state) IDLE: if(/*触发条件*/) next_state = CMD_SENDING; else next_state = IDLE; CMD_SENDING: if(/*完成发送命令*/) next_state = ADDR_SENDING; else next_state = CMD_SENDING; ADDR_SENDING: if(/*完成发送地址*/) next_state = DUMMY_CYCLE; else next_state = ADDR_SENDING; DUMMY_CYCLE: if(/*经过一定数量的空闲周期*/) next_state = DATA_READING; else next_state = DUMMY_CYCLE; DATA_READING: if(bit_cnt==7) next_state = IDLE; else next_state = DATA_READING; default : next_state = IDLE; endcase end // ...省略部分细节... endmodule ``` 此段程序展示了如何利用状态转换机制协调各个子任务之间的顺序关系,从而达到稳定可靠地获取外部存储单元内指定区域内容的目的。值得注意的是,上述例子仅提供了一个简化版框架结构,实际应用当中还需要考虑更多因素,例如错误检测与纠正功能的设计等问题[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值