最近对flask的热情有点下降,对tornado有点高涨。 之前在知乎上回答过一个问题,如何理解 Tornado ?,我的回答如下:
1.高性能的网络库,这可以和gevent,twisted,libevent等做对。
提供了异步io支持,超时事件处理,在此基础上提供了tcpserver,httpclient,尤其是curlhttpclient,
在现有http客户端中肯定排第一。可以用来做爬虫,游戏服务器,据我所知业界已有使用tornado作为游戏服务器
2.web框架,这可以和django,flask对。
提供了路由,模板等web框架必备组件。与其他区别是tornado是异步的,天然适合长轮训,
这也是friendfeed发明tornado的原因,当前flask也可以支持,但必须借助gevent等
3.较为完备的http服务器,这点可以和nginx,apache对比,
但只支持http1.0,所以使用nginx做前段不仅是为了更好利用多核,也是让其支持http1.1
4.完备的wsgi服务器,这可以和gunicore,gevent wsgi server做对比,
也就是说可以让flask运行在tornado之上,让tornado加速flask
5.提供了完备的websocket支持,这让html5的游戏等提供了便利。
像知乎长轮训就是使用了websocket,但websocket手机支持的不是很好,
前段时间不得不使用定时ajax发送大量请求,期待手机浏览器赶快奋起直追
最近研究了下tornado的模板,实现的比较简洁,在这里总结一下。
tornado的模板基本都在template.py这个文件中,短短800多行代码就实现了基本可用的模板,让我们慢慢揭开她的面纱。
首先我们看看tornado是如何编译模板的,下面是个简单的模板
t = Template("""\
{%if names%}
{% for name in names %}
{
{name}}
{%end%}
{%else%}
no one
{%end%}
""")
tornado最后编译代码如下:def _tt_execute(): # <string>:0
_tt_buffer = [] # <string>:0
_tt_append = _tt_buffer.append # <string>:0
if names: # <string>:1
_tt_append('\n ') # <string>:2
for name in names: # <string>:2
_tt_append('\n ') # <string>:3
_tt_tmp = name # <string>:3
if isinstance(_tt_tmp, _tt_string_types): _tt_tmp = _tt_utf8(_tt_tmp) # <string>:3
else: _tt_tmp = _tt_utf8(str(_tt_tmp)) # <string>:3
_tt_tmp = _tt_utf8(xhtml_escape(_tt_tmp)) # <string>:3
_tt_append(_tt_tmp) # <string>:3
_tt_append('\n ') # <string>:4
pass # <string>:2
_tt_append('\n') # <string>:5
pass # <string>:5
else: # <string>:5
_tt_append('\nno one\n') # <string>:7
pass # <string>:1
_tt_append('\n') # <string>:8
return _tt_utf8('').join(_tt_buffer) # <string>:0
是的,你没看错,tornado编译就是将之翻译成一个个代码块,最后通exec传递我们给的参数命名空间执行_tt_execute函数。
在我们上面的模板中包含了4种预定义的NODE节点,_ControlBlock,_Expression,_TEXT,每种Node节点都有自己的生成方式。
比如说_Expression表达式节点,也就是我们模板中的{ {name}},当_parse解析时发现'{'后面还是'{'就认为是表达式节点,
class _Expression(_Node