Python 搭建Web站点之Web服务器与Web框架


Posted in Python onNovember 06, 2016

之前用 Django 做过一个小的站点,感觉Django太过笨重,于是就准备换一个比较轻量级的 Web 框架来玩玩。Web.py 作者已经挂掉,项目好久没有更新,所以不准备用它。而 Flask 也是一个成熟的轻量级 Web 框架,在 github 上有众多的 Star 和 Fork,文档和扩展也很丰富,值得学习。

学习一个框架最好的方式就是用框架做一个项目,在实战中理解掌握框架。这里我用 Flask 框架,使用 Mysql 数据库做了一个 论坛系统 。麻雀虽小,五脏俱全,论坛效果图如下:

Python 搭建Web站点之Web服务器与Web框架

论坛系统截图

下面是论坛的基本功能:

完整的用户模块(注册、登录,更改、找回密码、信息修改、站内消息通知); 丰富的论坛模块(创建、回复话题,站内搜索,markdown支持,@user 提醒); 强大的后台管理,支持屏蔽用户、话题、评论,支持各种条件搜索话题、评论;

本博客将会用一系列文章,记录论坛系统搭建的过程,希望对刚入门Web开发的同学有所帮助。

我们经常听说 Django, Flask 这些 python 语言的Web 框架,那么框架到底是什么,Web框架和Web服务器(Nginx, Apache等)有什么区别?离开框架还能用 Python 搭建Web站点吗?要解决这些疑问,我们有必要来理解下 Web 服务器的工作原理,以及 Web 框架的本质。

Web 服务器

当我们在浏览器输入URL后,浏览器会先请求 DNS服务器,获得请求站点的 IP 地址 。然后发送一个HTTP Request(请求)给拥有该 IP 的主机,接着就会接收到服务器给我们的 HTTP Response(响应),浏览器经过渲染后,以一种较好的效果呈现给我们。这个过程中,正是Web服务器在幕后默默做贡献。

简单来说,Web服务器是在运行在物理服务器上的一个程序,它永久地等待客户端(主要是浏览器,比如Chrome,Firefox等)发送请求。当收到请求之后,它会生成相应的响应并将其返回至客户端。Web服务器通过HTTP协议与客户端通信,因此也被称为HTTP服务器。

Python 搭建Web站点之Web服务器与Web框架

Web 服务器

Web服务器的工作原理并不复杂,一般可分成如下4个步骤:建立连接、请求过程、应答过程以及关闭连接。

建立连接:客户机通过TCP/IP协议建立到服务器的TCP连接。 请求过程:客户端向服务器发送HTTP协议请求包,请求服务器里的资源文档。 应答过程:服务器向客户机发送HTTP协议应答包,如果请求的资源包含有动态语言的内容,那么服务器会调用动态语言的解释引擎负责处理“动态内容”,并将处理得到的数据返回给客户端。由客户端解释HTML文档,在客户端屏幕上渲染图形结果。 关闭连接:客户机与服务器断开。

下面我们实现一个简单的 Web 服务器。运行示例程序后,会监听本地端口 8000,在浏览器访问 http://localhost:8000 就能看到响应内容。而我们的程序也能够打印出客户端发来的请求内容,如下图:

Python 搭建Web站点之Web服务器与Web框架

简单Web服务器

这里Request 和 Response 都需要遵守 HTTP 协议,关于 HTTP 协议的详细内容,可以读读《HTTP 权威指南》,或者看我整理的HTTP 部分内容。

虽然说web服务器的主要工作是根据request返回response,但是实际中的 Web 服务器远远比上面示例的复杂的多,因为要考虑的因素实在是太多了,比如:

缓存机制:讲一些经常被访问的页面缓存起来,提高响应速度; 安全:防止黑客的各种攻击,比如 SYN Flood 攻击; 并发处理:如何响应不同客户端同时发起的请求; 日志:记录访问日至,方便做一些分析。

目前在UNIX和LINUX平台下使用最广泛的免费 Web 服务器有Apache和 Nginx 。

Web 应用程序

Web 服务器接受 Http Request,返回 Response,很多时候 Response 并不是静态文件,因此需要有一个应用程序根据 Request 生成相应的 Response。这里的应用程序主要用来处理相关业务逻辑,读取或者更新数据库,根据不同 Request 返回相应的 Response。注意这里并不是 Web 服务器本身来做这件事,它只负责 Http 协议层面和一些诸如并发处理,安全,日志等相关的事情。

应用程序可以用各种语言编写(Java, PHP, Python, Ruby等),这个应用程序会从Web服务器接收客户端的请求,处理完成后,再返回响应给Web服务器,最后由Web服务器返回给客户端。整个架构如下:

Python 搭建Web站点之Web服务器与Web框架

Web应用程序

以 Python 为例,使用Python开发Web,最原始和直接的办法是使用CGI标准,在1998年这种方式很流行。首先确保 Web 服务器支持CGI及已经配置了CGI的处理程序,然后设置好CGI目录,在目录里面添加相应的 python 文件,每一个 python 文件处理相应输入,生成一个 html 文件即可,如下例:

# !/usr/bin/python 
# -*- coding: UTF-8 -*- 
print "Content-type:text/html" 
print # 空行,告诉服务器结束头部 
print '<html>' 
print '<head>' 
print '<meta charset="utf-8">' 
print '</head>' 
print '<body>' 
print '<h2>Hello Word! 我是一个CGI程序</h2>' 
print '</body>' 
print '</html>'

这样在浏览器访问该文件就可以得到一个简单的 Hello World 网页内容。直接通过 CGI 写 Web 应用程序看起来很简单,每一个文件处理输入,生成html。但是实际开发中,可能会遇到许多不方便的地方。比如:

每个独立的CGI脚本可能会重复写数据库连接,关闭的代码; 后端开发者会看到一堆 Content-Type 等和自己无关的 html 页面元素; Web 框架

早期开发站点确做了许多重复性劳动,后来为了减少重复,避免写出庞杂,混乱的代码,人们将 Web 开发的关键性过程提取出来,开发出了各种 Web 框架。有了框架,就可以专注于编写清晰、易维护的代码,无需关心数据库连接之类的重复性工作。

其中一种比较经典的Web框架采用了 MVC 架构,如下图所示:

Python 搭建Web站点之Web服务器与Web框架

MVC 架构

用户输入 URL,客户端发送请求,控制器(Controller)首先会拿到请求,然后用模型(Models)从数据库取出所有需要的数据,进行必要的处理,将处理后的结果发送给 视图(View),视图利用获取到的数据,进行渲染生成 Html Response返回给客户端。

以 python web 框架 flask 为例,框架本身并不限定我们用哪种架构来组织我们的应用,不过 flask 可以很好地支持以 MVC 方式组织应用。

控制器:flask 可以用装饰器来添加路由项,如下:

@app.route('/') 
def main_page(): 
  pass

模型:主要用来取出需要的数据,如下面函数中操作:

@app.route('/') 
def main_page(): 
  """Searches the database for entries, then displays them.""" 
  db = get_db() 
  cur = db.execute('select * from entries order by id desc') 
  entries = cur.fetchall() 
  return render_template('index.html', entries=entries)

视图:flask 利用 jinja2 来渲染页面,下面的模版文件指定了页面的样式:

{% for entry in entries %} 
<li> 
 <h2>{{ entry.title }}</h2> 
 <div>{{ entry.text|safe }}</div> 
</li> 
{% else %} 
<li><em>No entries yet. Add some!</em></li> 
{% endfor %}

我们知道Python有着许多的 Web 框架,而同时又有着许多的 Web 服务器(Apache, Nginx, Gunicorn等),框架和Web服务器之间需要进行通信,如果在设计时它们之间不可以相互匹配的,那么选择了一个框架就会限制对 Web 服务器的选择,这显然是不合理的。

那么,怎样确保可以在不修改Web服务器代码或网络框架代码的前提下,使用自己选择的服务器,并且匹配多个不同的网络框架呢?答案是接口,设计一套双方都遵守的接口就可以了。对python来说,就是WSGI(Web Server Gateway Interface,Web服务器网关接口)。其他编程语言也拥有类似的接口:例如Java的Servlet API和Ruby的Rack。

Python WSGI的出现,让开发者可以将 Web 框架与 Web 服务器的选择分隔开来,不再相互限制。现在,你可以真正地将不同的 Web 服务器与Web框架进行混合搭配,选择满足自己需求的组合。例如,可以使用 Gunicorn 或Nginx/uWSGI来运行Django、Flask或web.py应用。

Python 搭建Web站点之Web服务器与Web框架

WSGI 适配

下一篇我们将会仔细分析 WSGI 接口标准,然后一起来写一个简单的 WSGI Web 服务器。

Python 相关文章推荐
Python3.x对JSON的一些操作示例
Sep 01 Python
几种实用的pythonic语法实例代码
Feb 24 Python
使用Python搭建虚拟环境的配置方法
Feb 28 Python
django 实现celery动态设置周期任务执行时间
Nov 19 Python
使用Python测试Ping主机IP和某端口是否开放的实例
Dec 17 Python
python GUI库图形界面开发之PyQt5结合Qt Designer创建信号与槽的详细方法与实例
Mar 08 Python
Python通过Pillow实现图片对比
Apr 29 Python
浅谈Python中threading join和setDaemon用法及区别说明
May 02 Python
Python Request类源码实现方法及原理解析
Aug 17 Python
用Python进行websocket接口测试
Oct 16 Python
Python如何利用正则表达式爬取网页信息及图片
Apr 17 Python
Python可视化学习之matplotlib内置单颜色
Feb 24 Python
读写json中文ASCII乱码问题的解决方法
Nov 05 #Python
django1.8使用表单上传文件的实现方法
Nov 04 #Python
Python+MongoDB自增键值的简单实现
Nov 04 #Python
基于Python的接口测试框架实例
Nov 04 #Python
浅谈Python爬取网页的编码处理
Nov 04 #Python
Django接受前端数据的几种方法总结
Nov 04 #Python
Python多维/嵌套字典数据无限遍历的实现
Nov 04 #Python
You might like
基于PHP的cURL快速入门教程 (小偷采集程序)
2011/06/02 PHP
php多层数组与对象的转换实例代码
2013/08/05 PHP
浅谈PHP中类和对象的相关函数
2017/04/26 PHP
Laravel 中创建 Zip 压缩文件并提供下载的实现方法
2019/04/02 PHP
如何在Laravel5.8中正确地应用Repository设计模式
2019/11/26 PHP
PHP变量的作用范围实例讲解
2020/12/22 PHP
告诉大家什么是JSON
2008/06/10 Javascript
对jQuery的事件绑定的一些思考(补充)
2013/04/20 Javascript
jquery简单的拖动效果实现原理及示例
2013/07/26 Javascript
js传参数受特殊字符影响错误的解决方法
2013/10/21 Javascript
利用jquery写的左右轮播图特效
2014/02/12 Javascript
javascript 回到顶部效果的实现代码
2014/02/17 Javascript
js实现点击左右按钮轮播图片效果实例
2015/01/29 Javascript
js中的内部属性与delete操作符介绍
2015/08/10 Javascript
使用JS 插件qrcode.js生成二维码功能
2017/02/20 Javascript
详解Vue-Cli 异步加载数据的一些注意点
2017/08/12 Javascript
移动设备手势事件库Touch.js使用详解
2017/08/18 Javascript
React.Js添加与删除onScroll事件的方法详解
2017/11/03 Javascript
生产制造追溯系统之再说条码打印
2019/06/03 Javascript
jQuery实现简易聊天框
2020/02/08 jQuery
JS实现TITLE悬停长久显示效果完整示例
2020/02/11 Javascript
js实现坦克大战游戏
2020/02/24 Javascript
纯JS开发baguetteBox.js响应式画廊插件
2020/06/28 Javascript
Collatz 序列、逗号代码、字符图网格实例
2017/06/22 Python
python中logging包的使用总结
2018/02/28 Python
Python json模块与jsonpath模块区别详解
2020/03/05 Python
Python命名空间namespace及作用域原理解析
2020/06/05 Python
英国著名的化妆品折扣网站:Allbeauty.com
2016/07/21 全球购物
Smallable英国家庭概念店:设计师童装及家居装饰
2017/07/05 全球购物
MATCHESFASHION澳大利亚/亚太地区:英国时尚奢侈品电商
2020/01/14 全球购物
有针对性的求职自荐信
2013/11/14 职场文书
婚前协议书
2014/04/15 职场文书
推荐信格式要求
2014/05/09 职场文书
现实表现证明材料
2015/06/19 职场文书
领导新年致辞2016
2015/07/29 职场文书
写好求职信的技巧解密
2019/05/14 职场文书