本文不涉及WSGI的具体协议的介绍,也不会有协议完整的实现,甚至描述中还会掺杂着本人自己对于WSGI的见解。所有的WSGI官方定义请看http://www.python.org/dev/peps/pep-3333/。
WSGI是什么?
WSGI的官方定义是,the Python Web Server Gateway Interface。从名字就可以看出来,这东西是一个Gateway,也就是网关。网关的作用就是在协议之间进行转换。
也就是说,WSGI就像是一座桥梁,一边连着web服务器,另一边连着用户的应用。但是呢,这个桥的功能很弱,有时候还需要别的桥来帮忙才能进行处理。
下面对本文出现的一些名词做定义。 wsgi app ,又称 应用 ,就是一个WSGI application。 wsgi container ,又称 容器 ,虽然这个部分常常被称为handler,不过我个人认为handler容易和app混淆,所以我称之为容器。 wsgi_middleware ,又称 中间件 。一种特殊类型的程序,专门负责在容器和应用之间干坏事的。
一图胜千言,直接来一个我自己理解的WSGI架构图吧。
可以看出,服务器,容器和应用之间存在着十分纠结的关系。下面就要把这些纠结的关系理清楚。
WSGI应用
WSGI应用其实就是一个callable的对象。举一个最简单的例子,假设存在如下的一个应用:
Python代码 收藏代码
def application(environ, start_response):
status = '200 OK'
output = 'World!'
response_headers = [('Content-type', 'text/plain'),
('Content-Length', str(12)]
write = start_response(status, response_headers)
write('Hello ')
return [output]
这个WSGI应用简单的可以用简陋来形容,但是他的确是一个功能完整的WSGI应用。只不过给人留下了太多的疑点,environ是什么?start_response是什么?为什么可以同时用write和return来返回内容?
对于这些疑问,不妨自己猜测一下他的作用。联想到CGI,那么environ可能就是一系列的环境变量,用来表示HTTP请求的信息,比如说 method之类的。start_response,可能是接受HTTP response头信息,然后返回一个write函数,这个write函数可以把HTTP response的body返回给客户端。return自然是将HTTP response的body信息返回。不过这里的write和函数返回有什么区别?会不会是其实外围默认调用write对应用返回值进行处理?而且为什么 应用的返回值是一个列表呢?说明肯定存在一个对应用执行结果的迭代输出过程。难道说他隐含的支持iterator或者generator吗?
等等,应用执行结果?一个应用既然是一个函数,说明肯定有一个对象去执行它,并且可以猜到,这个对象把environ和start_response传给应用,将应用的返回结果输出给客户端。那么这个对象是什么呢?自然就是WSGI容器了。
WSGI容器
先说说WSGI容器的来源,其实这是我自己编造出来的一个概念。来源就是JavaServlet容器。我个人理解两者有相似的地方,就顺手拿过来用了。
WSGI容器的作用,就是构建一个让WSGI应用成功执行的环境。成功执行,意味着需要传入正确的参数,以及正确处理返回的结果,还得把结果返回给客户端。
所以,WSGI容器的工作流程大致就是,用webserver规定的通信方式,能从webserver获得正确的request信息,封装好,传给WSGI应用执行,正确的返回response。
一般来说,WSGI容器必须依附于现有的webserver的技术才能实现,比如说CGI,FastCGI,或者是embed的模式。
下面利用CGI的方式编写一个最简单的WSGI容器。关于WSGI容器的协议官方文档并没有具体的说如何实现,只是介绍了一些需要约束的东西。具体内容看PEP3333中的协议。
Python代码 收藏代码
#!/usr/bin/python
#encoding:utf8
import cgi
import cgitb
import sys
import os
#Make the environ argument
environ = {}
environ['REQUEST_METHOD'] = os.environ['REQUEST_METHOD']
environ['SCRIPT_NAME'] = os.environ['SCRIPT_NAME']
environ['PATH_INFO'] = os.environ['PATH_INFO']
environ['QUERY_STRING'] = os.environ['QUERY_STRING']
environ['CONTENT_TYPE'] = os.environ['CONTENT_TYPE']
environ['CONTENT_LENGTH'] = os.environ['CONTENT_LENGTH']
environ['SERVER_NAME'] = os.environ['SERVER_NAME']
environ['SERVER_PORT'] = os.environ['SERVER_PORT']
environ['SERVER_PROTOCOL'] = os.environ['SERVER_PROTOCOL']
environ['wsgi.version'] = (1, 0)
environ['wsgi.url_scheme'] = 'http'
environ['wsgi.input'] = sys.stdin
environ['wsgi.errors'] = sys.stderr
environ['wsgi.multithread'] = False
environ['wsgi.multiprocess'] = True
environ['wsgi.run_once'] = True
#make the start_response argument
#注意,WSGI协议规定,如果没有body内容,是不能返回http response头信息的。
sent_header = False
res_status = None
res_headers = None
def write(body):
global sent_header
if sent_header:
sys.stdout.write(body)
else:
print res_status
for k, v in res_headers:
print k + ': ' + v
print
sys.stdout.write(body)
sent_header = True
def start_response(status, response_headers):
global res_status
global res_headers
res_status = status
res_headers = response_headers
return write
#here is the application
def application(environ, start_response):
status = '200 OK'
output = 'World!'
response_headers = [('Content-type', 'text/plain'),
('Content-Length', str(12)]
write = start_response(status, response_headers)
write('Hello ')
return [output]
#here run the application
result = application(environ, start_response)
for value in result:
write(value)
看吧。其实实现一个WSGI容器也不难。
不过我从WSGI容器的设计中可以看出WSGI的应用设计上面存在着一个重大的问题就是:为什么要提供两种方式返回数据?明明只有一个write 函数,却既可以在application里面调用,又可以在容器中传输应用的返回值来调用。如果说让我来设计的话,直接把start_response给 去掉了。就用application(environ)这个接口。传一个方法,然后返回值就是status, response_headers和一个字符串的列表。实际传输的方法全部隐藏了。用户只需要从environ中读取数据处理就行了。。
可喜的是,搜了一下貌似web3的标准里面应用的设计和我的想法类似。希望web3协议能早日普及。
Middleware中间件
中间件是一类特殊的程序,可以在容器和应用之间干一些坏事。。其实熟悉python的decorator的人就会发现,这和decoraotr没什么区别。
下面来实现一个route的简单middleware。
Python代码 收藏代码
class Router(object):
def __init__(self):
self.path_info = {}
def route(self, environ, start_response):
application = self.path_info[environ['PATH_INFO']]
return application(environ, start_response)
def __call__(self, path):
def wrapper(application):
self.path_info[path] = application
return wrapper
这就是一个很简单的路由功能的middleware。将上面那段wsgi容器的代码里面的应用修改成如下:
Python代码 收藏代码
router = Router()
#here is the application
@router('/hello')
def hello(environ, start_response):
status = '200 OK'
output = 'Hello'
response_headers = [('Content-type', 'text/plain'),
('Content-Length', str(len(output)))]
write = start_response(status, response_headers)
return [output]
@router('/world')
def world(environ, start_response):
status = '200 OK'
output = 'World!'
response_headers = [('Content-type', 'text/plain'),
('Content-Length', str(len(output)))]
write = start_response(status, response_headers)
return [output]
#here run the application
result = router.route(environ, start_response)
for value in result:
write(value)
这样,容器就会自动的根据访问的地址找到对应的app执行了。
延伸
写着写着,怎么越来越像一个框架了?看来Python开发框架真是简单。。
其实从另外一个角度去考虑。如果把application当作是一个运算单元。利用middleware调控IO和运算资源,那么利用WSGI组成一个分布式的系统。
- 浏览: 142279 次
- 性别:
相关推荐
windows下使用flask+wsgi+Apache部署python web, 博客地址 https://blog.csdn.net/Albert201605/article/details/115429256
"PythonWeb开发案例教程_源代码.zip"这个压缩包包含了整个教程的实践代码,这将帮助你更好地跟随教程的步伐,亲手操作每一个示例,加深对理论知识的理解。 Python Web开发主要依赖于一些强大的框架,如Django、...
为了让大家更好的对python中WSGI有更好的理解,我们先从最简单的认识WSGI着手,然后介绍一下WSGI几个经常使用到的接口,了解基本的用法...WSGI,全称 Web Server Gateway Interface,或者 Python Web Server Gateway In
2. **WSGI(Web Server Gateway Interface)**:Python标准的Web服务器接口,定义了Web服务器如何与Web应用程序交互。 3. **模板引擎**:如Jinja2,用于生成HTML页面,允许开发者将动态数据嵌入到静态模板中。 4. **...
常用的Python Web服务器包括WSGI(Web Server Gateway Interface)服务器如Gunicorn和uWSGI,以及ASGI(Asynchronous Server Gateway Interface)服务器如Daphne和Uvicorn。 4. 数据库操作:在Web开发中,数据库是...
Web服务器网关接口(WSGI)是Python社区定义的一个标准接口,它定义了Web服务器与Python Web应用程序或框架之间的交互方式。通过WSGI,开发者可以专注于编写应用逻辑,而无需关心服务器的具体实现细节。 `mod_wsgi`...
作为Web框架,是一个轻量级的Web框架,类似于另一个Python web框架Web.py,其拥有异步非阻塞IO 的处理方式。 作为Web服务器,Tornado 有较为出色的抗负载能力,官方用nginx反向代理的方式部署Tornado和其它 Python ...
Python内置的WSGI服务器是Python标准库中的一个轻量级Web服务器,主要用于开发和测试目的。WSGI(Web Server Gateway Interface)是一种Web服务器与Web应用之间的接口标准,它定义了两者如何交互,使得不同的Web...
在"Pythonweb框架所需资料"这个资源中,我们可以找到与WSGI(Web Server Gateway Interface)协议和一个简单的web框架(mini_frame)相关的学习材料。这些内容通常包括代码示例、解释文档以及可能的测试案例。 首先...
如果我们的Web应用是采用Python开发,而且符合WSGI规范,比如基于Django,Flask等框架,那如何将其部署在Apache中呢?本文中,我们就会介绍如何使用Apache模块mod_wsgi来运行Python WSGI应用。 安装mod_wsgi 我们...
《PythonWeb项目开发实战教程(Flask版)》是一本以Flask框架为核心的Web开发教程,旨在帮助读者深入理解和掌握使用Python进行Web开发的技术。Flask是一个轻量级的Web服务器网关接口(WSGI)Web应用框架,以其简洁、...
Python Web实战指南是一本深入探讨如何使用Python语言构建Web应用的书籍。这本书涵盖了从基础到高级的多个主题,旨在帮助读者掌握开发Web应用的核心技能。以下是对书中可能涉及的一些关键知识点的详细阐述: 1. **...
- **WSGI模型**:Python Web应用通常遵循WSGI(Web Server Gateway Interface)模型,这是一种规范,用于定义Web服务器、应用程序和中间件之间如何通信。虽然WSGI模型不支持异步处理,但对于大多数Web应用来说已经...
Python Web开发是一个涵盖广泛的主题,包括使用Python语言构建动态、交互式的Web应用程序。这份"PYTHON WEB开发学习实录.pdf"很可能是对这个领域的全面指南,旨在帮助初学者和有一定经验的开发者深入理解Python在Web...
Python Web开发是现代互联网行业中非常流行的技术栈,它利用Python语言的强大功能构建高效、可扩展的Web应用程序。这个"Python Web开发学习实录-源代码"的资源集合为初学者和有经验的开发者提供了深入学习Python Web...
本主题将深入探讨如何使用Python编写一个简单的Web服务器,该服务器还具备加载图片的功能,并基于WSGI(Web Server Gateway Interface)协议。首先,让我们理解WSGI的基本概念。 WSGI是Python Web应用的标准接口,...
本文将深入探讨Python中的WSGI(Web Server Gateway Interface)服务器及其在WSGIserver-1.0-py2.py3-none-any.whl这个特定库中的应用。WSGI是Python Web应用程序与Web服务器之间的一个接口标准,它定义了如何处理...
在Python web开发中,WSGI(Web Server Gateway Interface)是一种标准接口,用于web服务器与web应用之间的通信。这个接口定义了一种规范,使得不同的服务器和应用程序可以协同工作,提高了代码的可移植性和灵活性。...