Python Falcon 简明教程

Python Falcon - WSGI vs ASGI

Web Server Gateway Interface(WSGI)

一些最流行的 Python Web 框架实现了 WSGI(代表 Web Server Gateway Interface )。WSGI 本质上是一组规范,用于 Web 服务器和 Web 应用程序之间的通用接口,由 Web 服务器软件实现,用于处理基于 Python 的 Web 应用程序的请求。WSGI 规范最初于 2003 年引入(PEP 333),并于 2010 年进行更新(PEP 3333)。

Some of the most popular Python web frameworks implement WSGI (stands for Web Server Gateway Interface). WSGI is essentially a set of specifications for a universal interface between web server and web applications, to be implemented by web server software for handling requests from Python-based web application. WSGI specifications were first introduced in 2003 (PEP 333) and later updated in 2010 (PEP 3333).

服务器通过传递以下参数来调用 WSGI 应用程序对象 −

A WSGI Application object is invoked by the server by passing the following arguments −

  1. environ − A Python dict object which is similar to CGI environment variables and certain WSGI specific variables.

  2. start_response − A callback function to be used by the application to return its response along with headers and status code.

此对象可以是 Python 中的任意可调用对象,例如带 call() 方法的函数、方法、类或其实例。此应用程序对象必须返回一个包含单个字节字符串的迭代器。

This object can be any callable object as in Python such as a function, method, a class or its instance with call() method available to it. This application object must return an iterator consisting of a single byte string.

def application (environ, start_response):
   ...
   ...
   return [("Hello World!".encode("utf-8")]

但是,启用 WSGI 的服务器在运行时是同步的,因此,应用程序不够高效。Python 通过引入 asyncio 模块作为标准库的一部分,从 3.4 版开始支持异步编程。

However, WSGI-enabled servers are synchronous in operation, because of which the applications are not that efficient. Python started asynchronous programming support with version 3.4 by introducing the asyncio module as a part of the standard library.

asyncio 模块提供在 Python 应用程序中并入并发编程样式的能力(通常称为协作式多任务处理)。在这种方法中,操作系统不会妨碍不同进程之间的上下文切换。取而代之的是,进程定期让步以容纳其他进程,以便许多应用程序可以同时运行。

The asyncio module provides the ability to incorporate in Python applications a style of concurrent programming (which is often called cooperative multitasking). In this approach, the operating system doesn’t obstruct the context switching among different processes. Instead, a process yields periodically to accommodate other processes so that many applications can run simultaneously.

在 Python 的 3.5 版中,添加了这两个关键字 asyncawait 。使用 async 关键字定义的 Python 函数称 coroutine 为,因此不能像普通函数一样运行。取而代之的是,我们需要使用 asyncio.run (coroutine) 调用它。可以通过 await 关键字使协程的执行暂停,直到另一个协程完成。

In Python’s version 3.5, these two keywords async and await were added. A Python function defined with the async keyword becomes a coroutine and hence can’t be run like a normal function. Instead, we need to call it using asyncio.run (coroutine). The execution of a coroutine can be made to pause till the completion of another coroutine by the await keyword.

import asyncio
async def main():
   print('hello')
   await asyncio.sleep(5)
   print('world')

asyncio.run(main())

Asynchronous Server Gateway Interface(ASGI)

ASGI 代表 Asynchronous Server Gateway Interface (根据其官方文档,它是 WSGI 的精神继承者),它为 Python Web 服务器、应用程序和框架增加了异步功能。

ASGI stands for Asynchronous Server Gateway Interface (as per its official documentation, it is a spiritual successor to WSGI), it adds the async capabilities to Python web servers, applications and frameworks.

ASGI 应用程序是一个异步可调用对象(用户定义的函数或具有 call() 方法的类的对象)。它获取三个参数,如下所示:

An ASGI application is an asynchronous callable object (a user-defined function or an object of a class having call() method). It takes three arguments as follows −

  1. Scope − A dict containing details of a specific connection

  2. Send − An asynchronous callable, by which event messages can be sent to the client

  3. Receive − Another asynchronous callable. The application can receive event messages from the client.

下面是一个异步函数表示的简单 ASGI 应用程序的原型 −

Following is the prototype of a simple ASGI application represented by an asynchronous function −

async def app(scope, receive, send):
   assert scope['type'] == 'http'
   await send({
   'type': 'http.response.start',
   'status': 200,
   'headers': [
      [b'content-type', b'text/plain'],
   ],
})
await send({
   'type': 'http.response.body',
   'body': b'Hello, world!',
})