Home  >  Article  >  Backend Development  >  如何开发一个Python web框架?

如何开发一个Python web框架?

WBOY
WBOYOriginal
2016-06-06 16:22:451192browse

需要哪些预备知识,有什么要注意的,哪些流行的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中下载.
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn