本帖最后由 sinanjj 于 2010-8-25 00:00 编辑
原文: http://www.python.org/dev/peps/pep-0333/
Specification Overview
The WSGI interface has two sides: the "server" or "gateway" side, andthe "application" or "framework" side. The server side invokes acallable object that is provided by the application side. Thespecifics of how that object is provided are up to the server orgateway. It is assumed that some servers or gateways will require anapplication's deployer to write a short script to create an instanceof the server or gateway, and supply it with the application object.Other servers and gateways may use configuration files or othermechanisms to specify where an application object should beimported from, or otherwise obtained.
标准综述
WSGI 接口描述了server/gateway(web服务器)和application/framework(web开发框架)两者之间的通讯.
In addition to "pure" servers/gateways and applications/frameworks,it is also possible to create "middleware" components that implementboth sides of this specification. Such components act as anapplication to their containing server, and as a server to acontained application, and can be used to provide extended APIs,content transformation, navigation, and other useful functions.
可以用中间件来做接口中转
Throughout this specification, we will use the term "a callable" tomean "a function, method, class, or an instance with a __call__method". It is up to the server, gateway, or application implementingthe callable to choose the appropriate implementation technique fortheir needs. Conversely, a server, gateway, or application that isinvoking a callable must not have any dependency on what kind ofcallable was provided to it. Callables are only to be called, notintrospected upon.
在这个标准中, 我们用"一个可调用函数"来指代python中的函数/方法/类/拥有__call__方法的实例.
The Application/Framework Side
The application object is simply a callable object that accepts two arguments. The term "object" should not be misconstrued asrequiring an actual object instance: a function, method, class,or instance with a __call__ method are all acceptable foruse as an application object. Application objects must be able to be invoked more than once, as virtually all servers/gateways(other than CGI) will make such repeated requests.
web开发框架端接口
应用程序就是一个接受两个参数的可调用的对象. 这里的应用程序就是指一个url的处理函数/方法/类/有__call__方法的实例.
Here are two example application objects; one is a function, and theother is a class:
下边是两个例子(一个是函数, 一个是类):
def simple_app(environ, start_response): # 声明一个函数. 函数有两个参数, 一个是environ, 一个是start_respons,
"""Simplest possible application object""" # 最简单的wsgi标准调用
status = '200 OK' # 将"200 OK" 字符串放入status.
response_headers = [('Content-type','text/plain')] #序列里放了个元组, 然后赋值给response_headers
start_response(status, response_headers) # 此句说明1, start_response是个函数. 2, 这个函数有两个参数, 一个是status, 一个是response_headers, 3, status是个字符串. 4, response_headers是个序列, 里边放了元组, 元组的值是http头的返回头.
return ['Hello world!\n'] # 返回值应该是http 内容
(能定义的这么绕也真不容易啊...)
The Server/Gateway Side
The server or gateway invokes the application callable once for eachrequest it receives from an HTTP client, that is directed at theapplication. To illustrate, here is a simple CGI gateway, implementedas a function taking an application object. Note that this simpleexample has limited error handling, because by default an uncaughtexception will be dumped to sys.stderr and logged by the webserver.
web服务器端
web服务器每收到一次http请求就调用一次可调用函数. 为了解释, 这里有一个简单的CGI网关.
import os, sys # 包含库
def run_with_cgi(application): # 定义这个函数, 参数是application
environ = dict(os.environ.items()) # 当前系统环境变量字典形式放入environ变量
environ['wsgi.input'] = sys.stdin # 增加environ字典键值
environ['wsgi.errors'] = sys.stderr
environ['wsgi.version'] = (1,0)
environ['wsgi.multithread'] = False
environ['wsgi.multiprocess'] = True
environ['wsgi.run_once'] = True # 设置并增加环境变量
if environ.get('HTTPS','off') in ('on','1'): #如果键"HTTPS"值为"on"或者"1"
environ['wsgi.url_scheme'] = 'https'
else:
environ['wsgi.url_scheme'] = 'http'
headers_set = [] # 声明一个字典
headers_sent = []
def write(data): #声明一个函数, 有一个参数.
if not headers_set:
raise AssertionError("write() before start_response()")
elif not headers_sent:
# Before the first output, send the stored headers
status, response_headers = headers_sent[:] = headers_set
sys.stdout.write('Status: %s\r\n' % status)
for header in response_headers:
sys.stdout.write('%s: %s\r\n' % header)
sys.stdout.write('\r\n')
sys.stdout.write(data)
sys.stdout.flush()
def start_response(status,response_headers,exc_info=None):
if exc_info:
try:
if headers_sent:
# Re-raise original exception if headers sent
raise exc_info[0], exc_info[1], exc_info[2]
finally:
exc_info = None # avoid dangling circular ref
elif headers_set:
raise AssertionError("Headers already set!")
headers_set[:] = [status,response_headers]
return write
result = application(environ, start_response)
try:
for data in result:
if data: # don't send headers until body appears
write(data)
if not headers_sent:
write('') # send headers now if body was empty
finally:
if hasattr(result,'close'):
result.close()
(插入
python函数调用另一个函数的函数名做参数有什么意义?
函数也是对象,这样的好象就是可以做一个通用的框架。比如根据不同的内容调用不同的函数,可以把条件与函数存成一个对照表,然后动态查找函数进行调用。
最常见的就是做web,一个请求上来,webserver自动分析url,然后找到对应的函数进行调用。那么这一过程一般是有一个调度程序来完成,比如:
def login():pass def **ut():pass
controllers = {
'/login/': login,
'/**ut/':**ut,
}
def dispatcher(url, controllers):
func = controllers.get(url)
if func:
func()
else:
response('Wrong url!') )
|