tornado 源码之 StackContext(二)
StackContext allows applications to maintain threadlocal-like state
that follows execution as it moves to other execution contexts.an exception
handler is a kind of stack-local state and when that stack is suspended
and resumed in a new context that state needs to be preserved.一个栈结构的上下文处理类
异常处理也是一个栈结构的上下文应用
contents
example usage
1 |
|
head
1 | from __future__ import with_statement |
_State
1 | class _State(threading.local): |
StackContext
- 初始化时保持传入的上下文对象
- __enter__
- 保存当前的全局上下文
- append 新的上下文到全局上下文
- 构造新的上下文
- 进入新的上下文 __enter__
- __exit__
- 调用新的上下文 context __exit__
- 回复全局上下文
全局上下文保存整个执行程序的上下文(栈)
with StackContext(context) 使程序包裹在 (global_context, context) 上执行
执行完成后恢复全局上下文
1 | class StackContext(object): |
ExceptionStackContext
捕获上下文执行中抛出而又未被捕获的异常
作用类似 finally
用于执行在程序抛出异常后记录日志、关闭 socket 这些现场清理工作
如果 exception_handler 中返回 True, 表明异常已经被处理,不会再抛出
example
1 | from tornado import ioloop |
__exit__ 中捕获 with 语句所包裹的程序执行中所抛出的异常,调用注册的 exception_handler 进行处理
exception_handler 返回 True,则异常不会蔓延
1 | class ExceptionStackContext(object): |
NullContext
临时构造一个空的全局上下文
1 | class NullContext(object): |
wrap
- 比较当时的全局上下文(_state.contexts)和闭包中保存的上下文 (contexts)
- 如果当前上下文长度长,表面执行环境需要重新构造
- 如果有两者有任何一个上下文不同,执行环境也要重新构造
- 新建一个 NullContext(), 清除当前的_state.contexts(保存原来的,提出时复原)
- 以此为基础构造一个 contexts 上下文链
- 如果 contexts 是 当前上下文的一个 prefix,则将当前上下文的后续部分作为上下文链,前面共有的无需再构造
- 在新的上下文链(new_contexts)上执行 with 操作,保证 callback 的执行环境与当时保存时的一模一样
之所以进行这样复杂的操作,是为了对某些前面执行环境相同的情况省略前面的构造,节省时间,否则,可以用一行代替:
new_contexts = ([NullContext()] + [cls(arg) for (cls,arg) in contexts])
1 | def wrap(fn): |
copyright
author:bigfish
copyright: 许可协议 知识共享署名 - 非商业性使用 4.0 国际许可协议
Sync From: https://github.com/TheBigFish/blog/issues/10