如何开发一个Pythonweb框架?
时间:2021-07-01 10:21:17
帮助过:48人阅读
需要哪些预备知识,有什么要注意的,哪些流行的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
- 这里补充一下. 有朋友说现成的框架这么多,我们还需要开发一个吗? 需要, 不是要专业的做开发框架, 而是在开发框架的过程中,能够让我更加的理解, 认识框架, 对开发有很大的好处,所以我认为Web开发者都应该对框架有所了解(至少源码得读一遍).
- 写好一个Web框架不是一两天的事情,那我们可以先从写一个简单的开始, 不断进行重构,迭代.
- 需要掌握一些基础的知识, 协议, TCP, HTTP, WSGI. 网络IO模型(blocking/non-blocking, Sync/Async).
- 设计,一些好的框架都有一些好的设计在里面,让在此框架上开发的人员感觉很爽.
- 现成的一些框架, 读一些目前流行框架可以了解一些新开发技术, 益处多多. tornado, flask, 刚开始读的时候可以看框架最初的版本, 可以从http://github.com中下载.