当前位置:  开发笔记 > 编程语言 > 正文

如何开发一个Python web框架?

需要哪些预备知识,有什么要注意的,哪些流行的Pythonweb框架适合参考、学习?
需要哪些预备知识,有什么要注意的,哪些流行的Python web框架适合参考、学习?

回复内容:

谢邀( @WHPython ),第一次在知乎上回答问题,各位大牛见笑了。

那么首先是不好意思,因为小伙伴肯定也知道我们这里马上要考试了,所以我就简单写一点,一方面是要把一些平时作业补上,另一方面是我也要尽量避免涉及太高深的内容导致装*失败(毕竟太嫩没有工作经验),当然还有一个重要的原因是内容实在太庞杂啦。好的,我们就开始吧。

首先你需要知道一个Web应用基本的请求处理流程。以最简单最原始的动态网页为例,你点击链接(GET),提交表单(POST),就是与服务器端建立了连接之后发送了一个HTTP请求(RFC2616 5.1节,之后都以HTTP 1.1为例),里面至少有方法(动词,就是GET啦POST什么的,详见RFC2616第9节),地址(URL),HTTP版本,还可能带上Cookie(会话的一般实现机制),缓存相关的信息(RFC2616 13节),User-Agent串等等一堆信息。对于POST请求我们还有表单内容作为请求实体(RFC2616 7.2节),里面是你填写的表单内容。

于是我们有了一些关于请求的数据,不过现在一般来讲这些数据还在前端服务器(反向代理,比如nginx,暂且忽略掉负载均衡,反正是透明的,也不考虑裸WSGI容器直接扛请求的情况)的手上,还没有传进后端语言(这里是Python)。我们就针对每一种语言都有特定的机制,用来将HTTP的请求信息映射到相应的编程语言范畴,叫做Web服务器界面(Web server interface),通用如CGI/FCGI/SCGI,特定于某一语言如WSGI/PSGI/Rack/...,特定于某一操作系统如ISAPI(这货还活着?),一些已经不再使用的就不提了。总之在Python世界里这就是WSGI(PEP 3333, Web Server Gateway Interface),它就定义了Python语言与Web服务器之间的界面。在WSGI里,
  • 请求的处理过程被映射为对应用callable的调用(application(environ, start_response),知乎不支持inline代码块?);
  • 请求信息被映射到environ字典中的相应键值,比如请求方法被映射到environ['REQUEST_METHOD'],请求的“相对路径”被映射到environ['PATH_INFO'](过度简化;暂且不提WSGI应用挂载点,框架层一般也不用关心这个,挂载WSGI应用一般是WSGI容器如gunicorn、uWSGI之类组件的工作);
  • 发送响应头的动作被映射到调用start_response(status, response_headers)(不考虑可选的第三个参数异常信息);
  • 返回响应数据被映射到application返回iterable的动作。

于是响应便从Python返回到Web服务器,再被发送回浏览器,浏览器将响应内容渲染,一个请求就完成啦。


有了这样的感性认识,那么我们作为Python Web开发框架的作者,要做的事情就是在WSGI规范的基础之上,提供尽可能便捷的开发手段和尽可能低的框架开销,也即我们的代码将要工作在WSGI与业务逻辑的中间层。架构上,Web开发框架或多或少都遵循MVC的设计模式(Django管它叫MTV,其实差不多)。同时,由于框架位于中间件的位置,加上其鼓励模块化与代码复用的性质,自然需要为常见的HTTP操作提供抽象。这里就可以展开一些话题:

  • 请求路径到view/controller的映射,请求参数的解析(routing,也叫路由)。
    • 正则匹配的方案,比如Django内置了一个简单的正则表达式解析组件,能解析一般常见语法的正则表达式,把capturing groups解析成位置参数,named capturing groups解析成关键字参数。
    • 也有DSL的方案,比如Werkzeug的路由组件。
  • 请求实体的处理。表单解析,配合Web服务器进行上传文件处理。
    • 正常的urlencoded表单,JSON表单,text/plain数据,multi-part表单
    • multi-part附件,附件操作API
    • 大文件上传(这个一般会被前端服务器保存在磁盘上的临时文件里,比方说nginx就是这么实现的)。
  • 会话。HTTP是无状态(stateless)的,这个特点非常重要。如果没有会话,你连续做几个请求,却没有手段证明你们是同一个人/同一台机器(你完全可能是代理服务器)。
    • 存储会话数据的会话后端(内存数据结构?文件?RDBMS?Redis?Memcache?)
    • 安全机制(HMAC什么的,可以参考beaker的secure cookie实现)
    • 请求处理流程中的会话中间件(从Cookie中提取会话,从query string中提取会话,从自定义头中提取会话,等等)
  • View/Controller界面。发挥你的创造力,用上你的工程经验。
    • Function-based or Class-based views? 参考:Django, Bottle, web.py, Tornado等一票框架的做法
    • 框架的可选机制与服务如何暴露,
      • 装饰器?(比如@login_required 这种额外要求)
      • 回调?(能想到的只有Tornado和Twisted这种异步框架做事情的方式,还有整个JS生态系统都是回调(不考虑Promise什么的)的思路)
    • 传入应用(业务逻辑)层的数据结构如何设计?(HttpRequest等价物,名字可能记不清了)
    • 响应数据结构如何设计?(HttpResponse等价物,同上)
  • 数据库操作封装。Web应用基本都是数据为中心,这个组件非常有必要,也是撰写可复用代码必须的一环,毕竟光是框架抽象了,数据库操作还是裸SQL什么的,到时候生产环境一换(比如MySQL变pgsql)还不是傻眼。
    • 关系型数据库。一站式解决方案参考:Django ORM、SQLAlchemy;轻量级解决方案参考各数据库Python绑定。
    • 非关系数据库。各数据库Python绑定(pymongo, riak, redis-py之类),这个没什么可替代方案了,因为本来各种NoSQL库都是适应某一特殊需求设计的,没什么互相替换的必要,那意味着重新进行技术选型。
  • 未完待续

接下来的内容:

  • 主要响应AJAX/API请求的框架设计思路
  • Python下实时Web框架思路
  • 框架设计哲学
  • 框架性能分析方法

本人才疏学浅,大项目没做过,小项目也没怎么起飞过,请各位阅读我的观点时务必留心。读到最后非常感谢。



Changelog

  • 2014/12/28 18:25 第一次补充,昨天想写的时候已经上床了客户端不能编辑富文本哭哭哦
    • 我发现富文本编辑功能了,长期写reST和Markdown一时间不会用所见即所得编辑了
    • 给前面的内容加了一些例子,微调了一些叙述,具体的话我暂时懒得起git库管理了
    • 加上了框架数据库操作的内容
首先你要会用python
学个简单的web框架譬如flask什么的,了解框架应该有什么,大概怎么用的。
然后读一读bottle,一个文件而已,看懂之后,差不多了。
剩下的了解一些请求和请求处理知识,不懂的搜一搜 算是有始有终吧,做了个简单的,今天想起拿出来.ladder1984/globefish · GitHub 首先你的有一个成功的商业网站模式,类似linkedin,facebook之类的大网站,当然我们不可能写到那么大的架构。但前提这个网站模式得有其他人去用。不然写成框架给自己一个用也太TM浪费了。 Bottle single file
  1. 这里补充一下. 有朋友说现成的框架这么多,我们还需要开发一个吗? 需要, 不是要专业的做开发框架, 而是在开发框架的过程中,能够让我更加的理解, 认识框架, 对开发有很大的好处,所以我认为Web开发者都应该对框架有所了解(至少源码得读一遍).
  2. 写好一个Web框架不是一两天的事情,那我们可以先从写一个简单的开始, 不断进行重构,迭代.
  3. 需要掌握一些基础的知识, 协议, TCP, HTTP, WSGI. 网络IO模型(blocking/non-blocking, Sync/Async).
  4. 设计,一些好的框架都有一些好的设计在里面,让在此框架上开发的人员感觉很爽.
  5. 现成的一些框架, 读一些目前流行框架可以了解一些新开发技术, 益处多多. tornado, flask, 刚开始读的时候可以看框架最初的版本, 可以从github.com中下载.
推荐阅读
郑谊099_448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有