上月初开始实习的,想来一个月了,却一直没有时间更新博客,导致七月博客竟然一篇都没有……
学了三年Java,就因为接触了三个月的Python,于是就找了一个Python相关的实习,这厮太不“忠义”了……
过去的这个月,接触的最多的就是Python的WSGI了,WSGI不是框架不是模块,仅仅是一个规范协议,定义了一些接口,却影响着Python网络开发的方方面面。对于WSGI有这么一段定义:WSGI is the Web Server Gateway Interface. It is a specification for web servers and application servers to communicate with web applications (though it can also be used for more than that).我想我这篇文章不是详细介绍WSGI内容的,只是想扯扯我对WSGI相关的学习。
诚如那个WSGI的定义所说的,协议定义了一套接口来实现服务器端与应用端通信的规范化(或者说是统一化)。这是怎样的一套接口呢?很简单,尤其是对于应用端。
应用端只需要实现一个接受两个参数的,含有__call__方法的,返回一个可遍历的含有零个或多个string结果的Python对象(我强调说Python对象,只是想和Java的对象区别开,在Python里一个方法、一个类型……都是对象,Python是真“一切皆对象”,详见《Python源码分析》)即可。码农都知道,传入参数的名字可以任意取,这里也不例外,但习惯把第一个参数命名为“environ”,第二个为“start_response”。至于这个对象的内容怎样,应用自由发挥去吧……
服务器端要做的也不复杂,就是对于每一个来访的请求,调用一次应用端“注册”的那个协议规定应用端必须要实现的对象,然后返回相应的响应消息。这样一次服务器端与应用端的通信也就完成了,一次对用户请求的处理也随之完成了!当然了,既然协议规定了服务器端在调用的时候要传递两个参数,自然也规定了这两个参数的一些细节。比如第一个参数其实就是一个字典对象,里面是所有从用户请求和服务器环境变量中获取的信息内容,协议当然会定义一些必须有的值,及这些值对应的变量名;第二个参数其实就是一个回调函数,它向应用端传递一个用来生成响应内容体的write对象,这个对象也是有__call__方法的。
协议也提到了,还可以设计中间件来连接服务器端与应用端,来实现一些通用的功能,比如session、routing等。
具体怎么应用这个协议呢?Python自带的wsgiref模块有个简单的例子:
from wsgiref.simple_server import make_server
def hello_world_app(environ, start_response):
status = '200 OK' # HTTP Status
headers = [('Content-type', 'text/plain')] # HTTP Headers
start_response(status, headers)
# The returned object is going to be printed
return ["Hello World"]
httpd = make_server('', 8000, hello_world_app)
print "Serving on port 8000..."
# Serve until process is killed
httpd.serve_forever()
这个例子更多体现的是应用端的开发方法,很简单的按照协议实现一个了满足规范的方法,这样当浏览器向本机8000端口发起一个请求时,就会得到一个“Hello World”的字符串文本响应。这个例子虽然简单,但非常清楚的说明了应用端与服务器端的接口应用方式。
你可能会想到:现在对该端口的不同地址的请求都是由这个“hello_world_app”函数处理的,你可以实现一个功能,解析一下请求的PATH信息,针对不同的地址转发给不同的函数或是类来处理;你可能会觉得使用environ和start_response这两个参数不直观,你可以像Java的servlet那样自己封装成两个request和response对象来用;你觉得有些常用功能可以提取出来,在具体应用逻辑之外来做……哈哈,那你就已经在思考怎么做中间件或是Web框架了!其实这些也都有人做过了,比如Routes、WebOb、Beaker……当然你大可以自己造自己独有的轮子,有时候自己做过一遍了才会对现有的成熟的东西有更好的理解,最重要的是在Python的世界里这些都不难做到!
不知你是不是和我一样,在写应用的时候或多或少的会想一下服务器端是怎么运作的呢?可能最模糊的流程大家都能想得到:服务器开一个socket等待客户端连接;请求来了,服务器会读出传来的数据,然后根据HTTP协议做一些初步的封装,接着就可以调用事先注册的应用程序了,并将请求的数据塞进去;等响应处理完毕了再把数据通过socket发出去,over。好在Python的代码简洁,而自带的wsgiref中的simple server也很简单,就让我们探究一下更具体的实现吧!
首先看一下类的继承关系,这个simple server真正的类是WSGIServer,继承自HTTPServer,HTTPServer类又继承自TCPServer,TCPServer又继承自BaseServer;与server类直接打交道的还有RequestHandler类,从最上层的WSGIRequestHandler —> BaseHTTPRequestHandler —> StreamRequestHandler —> BaseRequestHandler。相对Java而言不是很复杂吧,它们是怎么工作的呢?容我稍微解释一下。
让我们从Server的最基类BaseServer看起。它有一段注释非常清楚的介绍了它定义的方法的用处:
Methods for the caller:
- __init__(server_address, RequestHandlerClass)
- serve_forever()
- handle_request() # if you do not use serve_forever()
- fileno() -> int # for select()
Methods that may be overridden:
- server_bind()
- server_activate()
- get_request() -> request, client_address
- verify_request(request, client_address)
- server_close()
- process_request(request, client_address)
- close_request(request)
- handle_error()
Methods for derived classes:
- finish_request(request, client_address)
可见,一个server类其实就这么几个方法。
在可以被外部调用的四个方法中,构造方法显然就是用来创建实例的;第四个可能是和构建异步服务器有关的,这里就略过了;从具体的代码可以看到,剩下两个方法的用处是相同的,就是处理收到的请求,只是serve_forever()方法会在server进程存在期间循环处理,而handle_request()处理一次就退出了(其实server_forever()就是循环调用了handle_request())。在handle_request()中说明了具体的从接受到返回一个请求的全部流程,代码也很简单:
def handle_request(self):
"""Handle one request, possibly blocking."""
try:
request, client_address = self.get_request()
except socket.error:
return
if self.verify_request(request, client_address):
try:
self.process_request(request, client_address)
except:
self.handle_error(request, client_address)
self.close_request(request)
BaseServer虽然定义了这些内部调用的方法,但内容基本都是空的,留给了具体的Server类去实现。从BaseServer的代码中就可以看到RequestHandler类的用处了,它是具体的解析了request的内容,它由finish_request()调用,而这个finsh_request()方法显然应该是在process_request()方法中被调用的。
TCPServer继承BaseServer类,它真正具体化了我们猜测的socket连接的初始化过程。
在与上面两个类相同的源文件中,还有两个主要的类:ThreadingMixIn和ForkingMixIn,这两个类分别重载了process_request()方法,并且相应使用了新建一个线程或是进程的方式来调用finish_request()方法。这也从应用的角度解释了为什么要在finish_request()外套一层process_request(),而不是直接在handle_request()的第二个try块中调用。
HTTPServer其实做的工作很简单,就是记录了socket server的名字。
接下来就该看看WSGIServer了。它做了两件新的工作:设置了一些基本的环境变量值,并且接受应用程序的注册。从这个Server的代码可以看出,应用端实现的那个接口就是从这里注册到服务器端的,而且只能注册一个哦!所以要有多个应用只能通过routing的方式来转发调用了。而且这个WSGIServer不是多线程或是多进程的~
至于具体封装请求内容的RequestHandler类就不打算分析了,感兴趣的话,看官们自个看一下源码吧,也很简单哦!下一篇博客打算分享一下我对pylons框架的运行过程的学习。
分享到:
相关推荐
`cpp-modwsgi` 是一个专为Apache服务器设计的模块,它实现了Python的Web服务器网关接口(WSGI)标准。这个模块,通常称为`mod_wsgi`,使得开发者可以使用Python语言来编写Web应用,并在Apache环境下运行。在本文中,...
### Linux+Django+Python+Wsgi配置过程 #### 一、环境准备与系统基本信息 根据提供的文件信息,本文档将详细介绍如何在Linux环境下配置Apache+Mod_Wsgi+Django环境的过程。具体步骤包括软件安装、项目部署等环节。...
Python WSGI(Web Server Gateway Interface)是一种标准接口,它定义了Web服务器如何与Web应用程序进行通信。这个规范由PEP 3333提出,旨在简化Python Web开发中的复杂性,让不同的服务器和框架之间能够更好地协同...
Python-Zappa 是一个开源工具,它为 Python 开发者提供了一种极其便捷的方式,将基于 WSGI(Web Server Gateway Interface)的 Python Web 应用部署到 AWS Lambda 和 API Gateway 上,实现“无服务器”架构。...
如果我们的Web应用是采用Python开发,而且符合WSGI规范,比如基于Django,Flask等框架,那如何将其部署在Apache中呢?本文中,我们就会介绍如何使用Apache模块mod_wsgi来运行Python WSGI应用。 安装mod_wsgi 我们...
python2.7+Django 1.11 在windows 下部署到apache24 下可用
Apache 2.2 和 Python 2.7 之间的交互主要依赖于一个名为 mod_wsgi 的模块,它是 Apache HTTP 服务器的一个扩展,允许在 Apache 上运行 Python Web 应用程序,特别是像 Django 这样的高级 Web 框架。在本场景中,...
`mod_wsgi` 是一款用于在Apache Web服务器上部署和运行Python Web应用程序的模块,它实现了WSGI(Web Server Gateway Interface)标准。WSGI是Python Web应用的通用接口,让Web服务器与Web应用之间能进行通信。通过`...
标题“mod_wsgi3.5(按照apache版本,python版本,系统版本选择使用)”指的是mod_wsgi的3.5版本,它是一个用于在Apache web服务器上运行Python应用的模块,特别是Django框架的应用。这个标题强调了在选择和安装mod_...
eventlet-Python支持 WSGI 的异步框架
Python 内置的 WSGI 服务器.py
3. **版本兼容性**:“mod_wsgi-3.5”可能有特定的Python版本要求,例如,可能只支持Python 2.7或Python 3.x的某个子版本。了解这些限制对于正确部署和运行Python应用至关重要。 4. **CPU架构**:此版本可能支持...
### Windows平台Apache 24与mod_wsgi部署Python应用详解 #### 一、概述 在Windows平台上部署Python Web应用时,经常会遇到各种各样的问题。本文将详细介绍如何使用Apache 2.4结合mod_wsgi模块来高效地部署Python...
Python内置的WSGI服务器是Python标准库中的一个轻量级Web服务器,主要用于开发和测试目的。WSGI(Web Server Gateway Interface)是一种Web服务器与Web应用之间的接口标准,它定义了两者如何交互,使得不同的Web...
标题中的“wsgi_lineprof-0.4.0-cp33-cp33m-manylinux1_x86_64.whl”是一款基于Python的WSGI(Web Server Gateway Interface)性能分析工具,名为wsgi_lineprof。这个库主要用于帮助开发者优化他们的Python WSGI应用...
资源分类:Python库 所属语言:Python 资源全名:necrophos-wsgi-0.0.1.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059
标题中的“wsgi_lineprof-0.8.0-cp37-cp37m-manylinux1_i686.whl”是一个针对Python的特定版本(3.7)的库,名为wsgi_lineprof,版本号为0.8.0。这个库主要用于Web服务器网关接口(WSGI)应用的性能分析,它提供了...
windows下使用flask+wsgi+Apache部署python web, 博客地址 https://blog.csdn.net/Albert201605/article/details/115429256