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 相关文章推荐
python启动办公软件进程(word、excel、ppt、以及wps的et、wps、wpp)
Apr 09 Python
教大家使用Python SqlAlchemy
Feb 12 Python
浅谈python中的getattr函数 hasattr函数
Jun 14 Python
Python 常用 PEP8 编码规范详解
Jan 22 Python
Python中动态创建类实例的方法
Mar 24 Python
Python读写docx文件的方法
May 08 Python
Python如何使用函数做字典的值
Nov 30 Python
Python Pandas 转换unix时间戳方式
Dec 07 Python
Python实现CNN的多通道输入实例
Jan 17 Python
Python安装第三方库攻略(pip和Anaconda)
Oct 15 Python
Python基于Serializer实现字段验证及序列化
Nov 04 Python
Ubuntu20.04环境安装tensorflow2的方法步骤
Jan 29 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 date函数参数详解
2006/11/27 PHP
php中取得URL的根域名的代码
2011/03/23 PHP
Linux下CoreSeek及PHP扩展模块的安装
2012/09/23 PHP
thinkphp3.2同时连接两个数据库的简单方法
2019/08/13 PHP
Laravel框架查询构造器 CURD操作示例
2019/09/04 PHP
简略的前端架构心得&amp;&amp;基于editor为例子的编码小技巧
2010/11/25 Javascript
jquery动态加载图片数据练习代码
2011/08/04 Javascript
javascript Event对象详解及使用示例
2013/11/22 Javascript
js游戏人物上下左右跑步效果代码分享
2015/08/28 Javascript
jQuery 弹出层插件(推荐)
2016/05/24 Javascript
JS判断字符串变量是否含有某个字串的实现方法
2016/06/03 Javascript
angularjs使用directive实现分页组件的示例
2017/02/07 Javascript
js实现文字列表无缝滚动效果
2017/06/23 Javascript
微信小程序左右滑动的实现代码
2017/12/15 Javascript
React Native自定义控件底部抽屉菜单的示例
2018/02/08 Javascript
async/await地狱该如何避免详解
2018/05/10 Javascript
详解create-react-app 自定义 eslint 配置
2018/06/07 Javascript
微信小程序chooseImage的用法(从本地相册选择图片或使用相机拍照)
2018/08/22 Javascript
vue-cli3脚手架的配置及使用教程
2018/08/28 Javascript
Vue.js 中的 v-model 指令及绑定表单元素的方法
2018/12/03 Javascript
jQuery实现数字自动增加或者减少的动画效果示例
2018/12/11 jQuery
详解Vue中watch对象内属性的方法
2019/02/01 Javascript
详解Vue组件之间通信的七种方式
2019/04/14 Javascript
Element-UI中关于table表格的那些骚操作(小结)
2019/08/15 Javascript
Django项目实战之用户头像上传与访问的示例
2018/04/21 Python
Python实现的爬取网易动态评论操作示例
2018/06/06 Python
python实现根据指定字符截取对应的行的内容方法
2018/10/23 Python
详解Django CAS 解决方案
2019/10/30 Python
纯CSS3实现3D旋转书本效果
2016/03/21 HTML / CSS
html5 canvas实现跟随鼠标旋转的箭头
2016/03/11 HTML / CSS
你的自行车健身专家:FaFit24
2016/11/16 全球购物
晚会开幕词
2015/01/28 职场文书
护林员个人总结
2015/03/04 职场文书
2015年关爱留守儿童工作总结
2015/05/22 职场文书
职工趣味运动会开幕词
2016/03/04 职场文书
25句企业管理语录:助你迅速打开思路,句句经典!
2020/01/14 职场文书