基于Web的应用程序(application)或接口(application interface)分为两个部分:Web服务器,负责实现HTTP协议的部分;应用程序部分负责实现业务逻辑的部分。
使用Python开发Web应用也必然需要和Web服务器进行交互,因此定义了一个简单通用的接口 WSGI (Web Server Gateway Interface,有时发音作'wiz-gee' 和'whiskey威士忌'的读音很像。
# app.py
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return ['<h1>Hello, web!</h1>'.encode("utf-8")]
environ: 是一个字典负责传递HTTP请求的信息:
HTTP_HOST 192.168.56.109:8080
HTTP_CONNECTION keep-alive
HTTP_PRAGMA no-cache
HTTP_CACHE_CONTROL no-cache
HTTP_USER_AGENT Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36
HTTP_ACCEPT image/webp,image/apng,image/*,*/*;q=0.8
HTTP_REFERER http://192.168.56.109:8080/where/am/i
HTTP_ACCEPT_ENCODING gzip, deflate
HTTP_ACCEPT_LANGUAGE zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
最后使用return返回HTTP的body信息。这里的.encode("utf-8")是为了配合下文的例子,在专用的WSGI服务器上可能不需要。
配合Python内置的一个最简单的WSGI服务器:
# wsgi.py
from wsgiref.simple_server import make_server
from app import application
# 服务器部分,IP地址为空监听所有本地IP,端口是8000,app函数是application:
httpd = make_server('', 8080, application)
print("Serving HTTP on port 8080...")
# 启动
httpd.serve_forever()
启动服务器:python3 wsgi.py
用浏览器或wget,curl等访问:http://127.0.0.1:8080/
wsgiref是Python内置的一个WSGI的简易实现,生产中应该使用uWSGI这种更可靠的服务器(uWSGI不是Python专用的,它也实现了其他语言的网关接口),在生产环境前边可能还会架设一个Nginx之类的更专业的Web服务器用来分发静态文件,提供其他功能支持。
当然,有了WSGI服务器还是不方便使用,这时一些Web框架就出场了,比如Django,Flask等,使用这些框架创建app对象,作为WSGI服务器的回调函数,更方便功能更丰富,相关的网站有对应的例子入门都很简单。
ASGI(Asynchronous Server Gateway Interface)是WSGI的继任者,旨在为支持异步功能的Python Web服务器,框架和应用程序之间提供标准接口。
WSGI只提供同步的接口,ASGI同时提供同步的和异步的接口,向后兼容WSGI标准。
ASGI的应用长这样:
# asgi.py
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!',
})
scope
- 一个包含连接信息的字典.receive
- 一个接收从服务器传入的信息的句柄send
- 一个往服务器发送信息的句柄看到async和await就明白了,这个是使用了Python的协程技术。
使用支持ASGI的服务器拉起来:
安装uvicorn: pip install uvicorn
uvicorn --host 0.0.0.0 --port 8080 asgi:app