`
angeloce
  • 浏览: 71754 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

PEP333 wsgi规范1.0不靠谱翻译稿(1)

阅读更多

摘要

This document specifies a proposed standard interface between web servers and Python web applications or frameworks, to promote web application portability across a variety of web servers.

 

为促进python的web应用在各类web服务器上的移植, 本文档指定了web服务器和python的web框架间的标准接口.

 

原理和目标

Python currently boasts a wide variety of web application frameworks, such as Zope, Quixote, Webware, SkunkWeb, PSO, and Twisted Web -- to name just a few [1]. This wide variety of choices can be a problem for new Python users, because generally speaking, their choice of web framework will limit their choice of usable web servers, and vice versa.

 

By contrast, although Java has just as many web application frameworks available, Java's "servlet" API makes it possible for applications written with any Java web application framework to run in any web server that supports the servlet API.

 

The availability and widespread use of such an API in web servers for Python -- whether those servers are written in Python (e.g. Medusa), embed Python (e.g. mod_python), or invoke Python via a gateway protocol (e.g. CGI, FastCGI, etc.) -- would separate choice of framework from choice of web server, freeing users to choose a pairing that suits them, while freeing framework and server developers to focus on their preferred area of specialization.

 

python目前拥有了大量的web框架,例如Zope, Quixote, Webware, SkunkWeb, PSO, Twisted Web.(想看更多点击http://wiki.python.org/moin/WebFrameworks .). 从如此多的框架中选择对刚刚进入python的新人来说是个问题,一般来说, 选择一个web框架限制了对web服务器的选择,反过来也一样.

 

相比之下,尽管 Java也有众多的web框架, Java的 servlet  API使得程序员可以使用任何Java web框架编写在能运行在任何web服务器上的程序,只要他们都支持servlet API.

 

概述

The WSGI interface has two sides: the "server" or "gateway" side, and the "application" or "framework" side. The server side invokes a callable object that is provided by the application side. The specifics of how that object is provided are up to the server or gateway. It is assumed that some servers or gateways will require an application's deployer to write a short script to create an instance of the server or gateway, and supply it with the application object. Other servers and gateways may use configuration files or other mechanisms to specify where an application object should be imported from, or otherwise obtained.

 

In addition to "pure" servers/gateways and applications/frameworks, it is also possible to create "middleware" components that implement both sides of this specification. Such components act as an application to their containing server, and as a server to a contained 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" to mean "a function, method, class, or an instance with a __call__ method". It is up to the server, gateway, or application implementing the callable to choose the appropriate implementation technique for their needs. Conversely, a server, gateway, or application that is invoking a callable must not have any dependency on what kind of callable was provided to it. Callables are only to be called, not introspected upon. 

 

WSGI接口有两个方面, server 或 gateway 服务端,  以及 application 或 framework 应用端. 服务端会调用一个应用端的可调用对象, 如何传递可调用对象的细节由服务端决定.有可能一些服务器要求应用程序的开发者写一个脚本来创建服务器/网关的一个实例来获得应用程序;另一些服务器可能使用配置文件或者其他的机制来制定哪里有一个需要被import/ obtain 的应用程序.

 

除了这些服务器,网管,应用程序和框架外,也可以创建了实现WSGI随意一侧接口的中间件组件.这些组件从服务器看就像应用,从应用程序看就像服务器,利用这样的组建可以提供更多的接口, 内容转换, 导航等等其他有用的功能.

 

在整个概述中,我们使用术语"callable"来表示一个函数,方法, 类或者一个实现了__call__方法的实例.可调用对象的实现要根据服务端和应用端的需求来选择合适的方法.相反, 服务端和应用端调用这个可调用对象的时候并不用去关心到底是谁提供给它的, 仅仅是调用它们而已, 而不会对它们内省.

 

The Application/Framework Side 应用端

 

 The application object is simply a callable object that accepts two arguments. The term "object" should not be misconstrued as requiring an actual object instance: a function, method, class, or instance with a __call__ method are all acceptable for use 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.

 

(Note: although we refer to it as an "application" object, this should not be construed to mean that application developers will use WSGI as a web programming API! It is assumed that application developers will continue to use existing, high-level framework services to develop their applications. WSGI is a tool for framework and server developers, and is not intended to directly support application developers.)

 

Here are two example application objects; one is a function, and the other is a class:

 

 

应用程序对象是一个需要接受两个参数的可调用对象. 这个术语"object(对象)"不应该被误解为需要一个对象实例: 函数,方法, 类, 实现了__call__方法的实例都可以作为一个应用程序对象来使用.应用程序对象必须能够被多次调用, 几乎所有的服务器/网关(除了CGI)都会制造重复请求.

 

(注意: 尽管我们一直说应用程序对象,  这不应该被理解为, 假设应用开发者使用已存在的高等web框架服务来开发他们的应用, 就必须使用WSGI作为web编程的API!WSGI对于框架和服务器开发者仅仅是一个工具,并没想要直接支持应用开发人员.)

 

这有两个例子,一个是函数,另一个是类:

def simple_app(environ, start_response):
    """Simplest possible application object"""
    status = '200 OK'
    response_headers = [('Content-type','text/plain')]
    start_response(status, response_headers)
    return ['Hello world!\n']

 

 

class AppClass:
    """Produce the same output, but using a class

    (Note: 'AppClass' is the "application" here, so calling it
    returns an instance of 'AppClass', which is then the iterable
    return value of the "application callable" as required by
    the spec.

    If we wanted to use *instances* of 'AppClass' as application
    objects instead, we would have to implement a '__call__'
    method, which would be invoked to execute the application,
    and we would need to create an instance for use by the
    server or gateway.
    """

    def __init__(self, environ, start_response):
        self.environ = environ
        self.start = start_response

    def __iter__(self):
        status = '200 OK'
        response_headers = [('Content-type','text/plain')]
        self.start(status, response_headers)
        yield "Hello world!\n"

 

 

The Server/Gateway Side 服务端

The server or gateway invokes the application callable once for each request it receives from an HTTP client, that is directed at the application. To illustrate, here is a simple CGI gateway, implemented as a function taking an application object. Note that this simple example has limited error handling, because by default an uncaught exception will be dumped to sys.stderr and logged by the web server.

 

服务器和网关在得到每一个http客户端的请求后都会调用一次可调用的应用对象, 请求直接用于应用.为了说明,这有一个简单的CGI网关,实现了一个获得了应用对象的函数.注意这个简单的例子已经限制了错误处理, 因为默认情况下一个未被捕捉到的异常会被发送到sys.stderr并在web服务器上记录下来.

 

import os, sys

def run_with_cgi(application):

    environ = dict(os.environ.items())
    environ['wsgi.input']        = sys.stdin
    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'):
        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()

 

 


Middleware: Components that Play Both Sides 中间件

Note that a single object may play the role of a server with respect to some application(s), while also acting as an application with respect to some server(s). Such "middleware" components can perform such functions as:

 

Routing a request to different application objects based on the target URL, after rewriting the environ accordingly.
Allowing multiple applications or frameworks to run side-by-side in the same process
Load balancing and remote processing, by forwarding requests and responses over a network
Perform content postprocessing, such as applying XSL stylesheets
The presence of middleware in general is transparent to both the "server/gateway" and the "application/framework" sides of the interface, and should require no special support. A user who desires to incorporate middleware into an application simply provides the middleware component to the server, as if it were an application, and configures the middleware component to invoke the application, as if the middleware component were a server. Of course, the "application" that the middleware wraps may in fact be another middleware component wrapping another application, and so on, creating what is referred to as a "middleware stack".

 

For the most part, middleware must conform to the restrictions and requirements of both the server and application sides of WSGI. In some cases, however, requirements for middleware are more stringent than for a "pure" server or application, and these points will be noted in the specification.

 

Here is a (tongue-in-cheek) example of a middleware component that converts text/plain responses to pig latin, using Joe Strout's piglatin.py. (Note: a "real" middleware component would probably use a more robust way of checking the content type, and should also check for a content encoding. Also, this simple example ignores the possibility that a word might be split across a block boundary.)

 

请注意一个单独的对象可能对于应用端扮演服务器的角色,对于服务端又扮演应用程序的角色. 这样的中间件可以实现这件功能:

 

1. 根据目标地址将请求发送给不同的应用程序对象,并在之后重写环境变量.

 

2. Allowing multiple applications or frameworks to run side-by-side in the same process
Load balancing and remote processing, by forwarding requests and responses over a network
Perform content postprocessing, such as applying XSL stylesheets

from piglatin import piglatin

class LatinIter:

    """Transform iterated output to piglatin, if it's okay to do so

    Note that the "okayness" can change until the application yields
    its first non-empty string, so 'transform_ok' has to be a mutable
    truth value."""

    def __init__(self,result,transform_ok):
        if hasattr(result,'close'):
            self.close = result.close
        self._next = iter(result).next
        self.transform_ok = transform_ok

    def __iter__(self):
        return self

    def next(self):
        if self.transform_ok:
            return piglatin(self._next())
        else:
            return self._next()

class Latinator:

    # by default, don't transform output
    transform = False

    def __init__(self, application):
        self.application = application

    def __call__(self, environ, start_response):

        transform_ok = []

        def start_latin(status,response_headers,exc_info=None):

            # Reset ok flag, in case this is a repeat call
            transform_ok[:]=[]

            for name,value in response_headers:
                if name.lower()=='content-type' and value=='text/plain':
                    transform_ok.append(True)
                    # Strip content-length if present, else it'll be wrong
                    response_headers = [(name,value)
                        for name,value in response_headers
                            if name.lower()<>'content-length'
                    ]
                    break

            write = start_response(status,response_headers,exc_info)

            if transform_ok:
                def write_latin(data):
                    write(piglatin(data))
                return write_latin
            else:
                return write

        return LatinIter(self.application(environ,start_latin),transform_ok)


# Run foo_app under a Latinator's control, using the example CGI gateway
from foo_app import foo_app
run_with_cgi(Latinator(foo_app))

 

 

分享到:
评论
1 楼 xi4nyu 2011-02-13  
不完整?

相关推荐

    Python PEP8 编码规范中文版.pdf

    PEP8 规范也提供了忽略规则的建议,例如当遵循这份指南之后代码的可读性变差,或者与周围的代码保持一致(也可能出于历史原因),或者代码需要兼容不支持编码规范建议的老版本 Python。 结语 PEP8 编码规范中文版...

    Python PEP8 编码规范中文版

    最后,PEP8规范也指出,如果遵循规范导致代码可读性变差,或者与周围的代码不一致,或者与老版本Python的兼容性有问题时,可以适当忽略某些规则。在这些情况下,最重要的是保持代码的清晰可读,以及与团队内部的风格...

    PEP8Python 编码规范

    PEP8是关于Python编码风格的规范,而如何将英文文档转成中文应当是遵循翻译原则和文档规范的问题。所以,正确理解这部分内容应该是:PEP8指导如何书写整洁的Python代码,并且在必要时如何将文档和注释用中文书写,...

    Python PEP8编码规范中文版

    PEP8编码规范,全称为“Style Guide for Python Code”,是由Python社区制定的一套编程风格指南,旨在提高Python代码的可读性和一致性。自2001年首版发布以来,经过多次修订和完善,PEP8已成为Python编程中普遍遵循...

    Python PEP8 编码规范中文版.zip

    **Python PEP 8编码规范中文版** Python PEP 8是Python编程语言的官方风格指南,由Guido van Rossum(Python之父)在2001年提出。PEP 8全称为"Python Enhancement Proposal 8",是Python社区广泛接受的代码风格指南...

    PEP8Python编码规范.pdf

    "PEP8 Python 编码规范" PEP8 是 Python 官方提供的一份编码规范指南,旨在提高 Python 代码的可读性、可维护性和可重用性。本文档将对 PEP8 中的各种规范进行详细解释和总结。 缩进和换行 PEP8 规定使用 4 个...

    PEP8代码规范

    ### PEP8代码规范详解 #### 一、引言 PEP8,即Python Enhancement Proposal 8,是一份详尽的文档,旨在规定Python代码的编写标准与规范。PEP8由Guido van Rossum等人制定,其核心目标是通过一系列明确的规则提升...

    python PEP8 编码规范总结

    参照https://legacy.python.org/dev/peps/pep-0008/官方文档简单总结了python编程过程中应当遵守的编码规范,比如函数的命名、变量的命名等(PEP8编码规范)。

    python pep8编码规范

    ### Python PEP8编码规范详解 #### 一、引言 PEP 8,全称为“Python Code Style Guide”,是Python官方推荐的编程规范指南。它由Python之父Guido van Rossum与其他开发者共同制定,并于2001年7月5日首次发布。PEP ...

    PEP8 Python编码规范

    PEP8是Python编程语言的官方编码规范,它由Python的核心开发者Guido van Rossum、Barry Warsaw和Nick Coghlan等人撰写和维护,最初于2001年发布。PEP是Python Enhancement Proposals的缩写,意为Python增强提案。PEP...

    Python编程规范PEP8.pdf

    1. 命名规范:PEP8提倡使用有意义的变量名和函数名,尽可能清晰表达其代表的含义。它推荐使用小写字母和下划线来命名变量和函数(snake_case),避免使用单个字符的变量名,除非是在非常有限的范围内使用,例如迭代...

    PEP8编码规范(中文)

    ### PEP8编码规范中文详解 #### 一、引言 PEP8 是 Python 编程语言中的一个重要标准,它提供了官方推荐的代码格式化规范。PEP8 的全称是“Python Enhancement Proposal 8”,它由 Guido van Rossum 和 Barry ...

    Python_PEP8_代码规范.pdf

    ### Python PEP8 代码规范详解 #### 一、引言 本文档旨在提供一份详细的指南,帮助开发者理解和遵循Python编程语言中广泛接受的最佳实践——PEP8代码规范。PEP8是Python Enhancement Proposal(Python改进提案)的...

    cpp-Meinheld是一个高性能的异步WSGIWeb服务器

    Meinheld完全遵循PEP333和PEP3333规范,这些是WSGI接口的标准定义。 **PEP333**,全称Python Enhancements Proposal 333,由Gustaf Niemeyer提出,首次定义了WSGI的基本概念和接口,规定了Web服务器如何处理请求...

    PEP5小学英语五年级下册课文及翻译.pdf

    PEP5小学英语五年级下册课文及翻译.pdf

    PythonPEP8编码规范中文版--高清.rar

    1. **缩进与空格**:PEP 8建议使用4个空格作为一级缩进,避免使用制表符,以减少不同编辑器显示不一致的问题。函数定义、类定义以及if、for、while等语句后的代码块应使用4个空格进行缩进。 2. **代码布局**:每行...

Global site tag (gtag.js) - Google Analytics