浅尝WSGI

标签:Python

由于很多Python的web框架在Google App Engine上的性能都不太好,因此想自己去做个框架,便研究了一下WSGI协议。

这个协议实际上很简单,就是建立一个服务器,这个服务器接收一个callable的对象application。
每当有访问,服务器就将环境变量environ和输出header所用的start_response函数传给application。
而application需要从environ里找出访问参数,用start_response输出header,并返回一个iterable的对象。
服务器接收到这个对象后,就会将它输出给访问者。

一个最简单的例子如下:
from wsgiref.simple_server import make_server

def application(environ, start_response):
    status = '200 OK'
    response_headers = [('Content-type','text/plain')]
    start_response(status, response_headers)
    return ['Hello']

httpd = make_server('', 80, application)
httpd.serve_forever()
运行这个例子,然后访问http://localhost/,就会收到看到'Hello'了。

当然也可以实现一个稍微复杂点的例子:
from wsgiref.simple_server import make_server

class application(object):
  def __call__(self, environ, start_response):
    start_response('200 OK', [('Content-type','text/plain')])
    return self.response(environ)

  def response(self, environ):
    for k, v in environ.iteritems():
      yield '%s: %s\n' % (k, v)

make_server('', 80, application()).serve_forever()
我将application改成了一个实现了__call__()的对象,然后返回一个generator对象。服务器会遍历这个generator对象并输出。(实际上''.join()就可以完成这个任务。)

而在GAE上则可以这样:
import wsgiref.handlers

def application(environ, start_response):
  start_response('200 OK', [('Content-type','text/plain')])
  return ['%s: %s\n' % (k, v) for k, v in environ.iteritems()]

def main():
  wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
  main()
可以看出,WSGI是很随意的,所以很多web框架都支持WSGI协议。

此外还有一点需要注意,字符串也是iterable对象,但最好别直接返回字符串,将其放在列表或元组中是更有效率的方法。
经我测试,使用yeild生成是最快的,但不能清空;调用列表的append()方法次之;最慢的是使用cStringIO(cStringIO在GAE上是可用的,速度比StringIO约快3倍)。

0条评论 你不来一发么↓

    想说点什么呢?