造轮子

       喜欢造轮子的我,那肯定也是实现过一套mvc的web框架的人,不止一套。 先前是用gevent做wsgi,jinja2做的模板,peewee做orm,我做了一个控制器来衔接各个组件,  如果想使用gevent的协程处理每个request_handler需要做一些妥协,比如第三方库的选择。 

       完成这一步之后,我觉得我不过瘾,索性直接自己写模板,自己写个易懂的orm,最后自己实现了一个类似tornado的异步框架,仿照Werkzeug来解析http协议,每个请求通过epoll做io调度,代理里存在各种的callback,各种的代码分段,各种的销魂….        

      上个月跟同事张磊大哥一起去参加雨痕的 《如何构建高性能web框架》的分享收益很多。 趁着这个热乎劲写写如何实现一个python的web框架.  


该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新。 http://xiaorui.cc/?p=3176


雨痕这次虽然没有过多说明mvc的实现细节,更多的是阐述了web框架的组件的选择,轮子要怎么造,轮子的深度怎么控制.   我虽然在线上都使用过的自己开发的web框架,但依旧觉得实现过程有些low ! 这次分享收获很大,可惜的是当时没有录像啥的. 


正题开始:

咱们先把web框架的模板实现给整明白,这在mvc里是重要的一环。 话说 python下的template模板还是不少的,独立的有mako,jinja2,另外像tornado,bottle,django自己也实现了一套模板。python模板大多数用在html网页中。 其实也可以来实现动态配置啥的。 


怎么实现python的模板,换句话说大多数模板都咋实现的? 

这是个很有意思的话题,以前因为没看过template代码实现,总以为就是正则替换,后来静下心的时候想想,单个变量还是挺好弄的,但是如果有有条件判断,循环语句, 特例函数怎么搞? 
这两天我看tornado,bottle关于template的代码实现,其实发现template远比我们想的有趣,他是把模板字符串中一些语法标记,转换成python语句执行。

我这里借鉴下别人的template代码,这代码的精简干练,要比django好讲解。 

https://raw.githubusercontent.com/mozillazg/lsbate/master/part2/template2d.py

自定义模板的关键字

任何一个模板都有模板的关键字及模板语法, 我们这里的 {{ var }} {% if var %} {% endif %} {% for item in items %} 这样都是关键字.   python中各个模板使用方法大同小异,没啥本质区别。

关键字解析

关键字的用途是用来拆解数据的,主要是通过关键词抽取tab,我们要把这些tab转换成python语句.   这里说下解析抽取的语法. 

返回的结果是被关键字用 , 分开. 

生成Python代码

我们拿到解析关键字的字符串后,还需要通过这些关键字来构建成python语句.  这里有个CodeBuilder类,这个类是控制python代码缩进的.


结果的返回结果是:
格式化后这样的:

字符串如何当成对象? 这里也不扯反射,自省模式啥的,没用.   python有个exec函数专门用来解决字符串对象化执行的. exec语句本来是用来执行存在于字符串、文件中的Python语句,很适合咱们这场景.

最后生成模板解析后的格式

namespace含有我们传递的字段数据,code_builder是有函数意义的字符串。 exec函数实现 func string –> func object . 
exec(func_string,namespace), exec会返回给我们func_string对象信息,及变量环境. 然后在namespace[func_name]()就可以正常执行的。
如果还是不理解exec在合理的用法,我这里演示下exec在template的用途.


总结, 这样虽然实现了模板,但是对于使用过jinja2的人来说,会发现这个自定义的模板功能显得很单薄。  没有filters自定义函数,另外安全也是个大问题,尤其我们这边使用了exec 大杀器, escape也是个有意思的话题。


下面是python template实现的全部代码:

END.



对Python及运维开发感兴趣的朋友可以加QQ群 : 478476595 !!!

另外如果大家觉得文章对你有些作用!   帮忙点击广告. 一来能刺激我写博客的欲望,二来好维护云主机的费用.
如果想赏钱,可以用微信扫描下面的二维码. 另外再次标注博客原地址  xiaorui.cc  ……   感谢!

关于海量数据处理的一些话题

这两天跟朋友聊了些关于海量数据的处理问题…    咱们暂且不提那些hadoop、spark的集群解决方案,就单单说海量数据的处理方式,一般面试题...

阅读全文

基于timerfd epoll开发的io定时器 [下]

接着上下文 接着上文, 上次内容是说epoll timerfd的原理和函数方法,下文主要是python epoll timerfd的之间的调用. 该文章写的有些乱,欢...

阅读全文

给redis-py提交pull request引起的思考

起因是这样的,昨天突然发现以前用redis python的时候,从来没注意过他在多线程,多进程下fd复用的情况,直接都是公用一个连接对象。  对比了多...

阅读全文