开发者学堂课程【Python 入门 2020年版:WSGI 服务器的介绍】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/639/detail/10482
WSGI 服务器的介绍
内容介绍:
一、WSGI 接口
二、应用
一、WSGI 接口
WSGI 接口定义非常简单,它只要求 Web 开发者实现一个函数,就可以响应 HTTP请求。
我们来看一个最简单的 Web 版本的 "Hello, web!":
def application(environ, start_ response):
start_ response('200 OK', [('Content-Type', 'text/html')])
return '<h1>Hello, web!</h1>'
上面的 application() 函数就是符合 WSGI 标准的一个 HTTP 处理函数,它接收两个参数: environ: 一个包含所有 HTTP 请求信息的 dict 对象;
start_ response:
一个发送 HTTP 响应的函数。
在 application() 函数中,调用:
start_ response('200 OK",[('Content-Type', 'text/htm1')1)
就发送了 HTTP 响应的 Header, 注意 Header 只能发送一次,也就是只能调用一次start _response()
函数。Start_response()
函数接收两个参数,一个是HTTP 响应码,一个是一组 list 表示的 HTTP Header, 每个 Header 用一个包含两个 str 的 tuple 表示。
通常情况下,都应该把 Content-Type 头发送给浏览器。其他很多常用的 HTTP Header 也应该发送。
二、应用
如果全部自己手写太麻烦了,我们可以使用 WSGI 服务器。
1. simple server 的使用
先给大家看个东西:
from wsgiref import simple server
If_name_=='_main_’:
with make_ server('', 8000, demo_ app) as httpd:
sa=httpd. socket. getsockname()
print("Serving HTTP on", sa[0], "port", sa[1], "...")
import webbrowser
webbrowser . open( http://localhost 8000/xyz?abc')
httpd . handle_ request() # serve one request, then exit
运行这个代码,显示如下图。
这就是 simple server 的写法,当我们运行的时候,它可以很快的创建一个服务器,在 make_server 里面返回了一个 server 的数据。原码就不给大家看了,简单来讲,就是把 socket 建立、绑定等等都帮我们写好了,是 Python 自带的文件帮我们做好了。
make_server 是创建一个服务器,相当于上一节课自己写的一个服务器,我们自己写一下:
from wsgiref.simple_server import make_server
if_ name_=='_ main_ ':
httpd : make_server(‘’, 8080, demo_app):
sa = httpd.socket. getsockname()
print("Serving HTTP on", sa[0], "port", sa[1], "...")
import webbrowser
webbrowser .open( ' http://localhost : 8000/xyz?abc')
httpd. handle_ request( ) # serve one request, then exit
导入模块的方法:Alt+Enter
2.写法讲解
这个写法就相当于给我们创建了一个对象,这个是帮我写好了,在它创建时需要服务器的地址等等都是需要的,最终也是需要端口号。
demo_app 是一个函数,用来处理用户的请求,当有请求时会自动调入 demo_app。
def demo_app():
Pass
下面 sa 是拿到 socket 的地址,服务器在 sa 的第 0 个,哪个端口号地址运行,告诉你是第几个,哪个 ip 地址以及端口号上运行。
import webbrowser 的作用是打开电脑的浏览器,并在浏览器里输入 http://localhost : 8000/xyz?abc,这个我们不用这个代码手动打开也行。
httpd. handle_ request( ) 这是指处理一次请求。运行一次之后,服务器就关了。
还有个方法叫 httpd.serve_forever(),这就相当于一个死循环,服务器在后台一直运行。
使用这个不需要我们创建 socket 再绑定地址。
3.demo_app 的使用
from wsgiref.simple_server import make_server
if_ name_=='_ main_ ':
httpd : make_server(‘’, 8080, demo_app):
sa = httpd.socket. getsockname()
print("Serving HTTP on", sa[0], "port", sa[1], "...")
import webbrowser
webbrowser .open( ' http://localhost : 8000/xyz?abc')
httpd.serve_forever() # serve one request, then exit
运行发现报错,原因:demo_app 使用时是有要求的。
要求:
(1)括号里需要两个参数 environ,start_response。
(2)第 0 个参数,表示环境(电脑的环境;请求路径相关的环境)
(3)第 1 个参数,是一个函数,用来返回响应头
(4)这个函数需要一个返回值,返回值是一个列表,列表里只有一个元素,是一个二进制,表示返回给浏览器的内容。
from wsgiref.simple_server import make_server
def demo_app(environ,start_response):
return [‘hello’.encode(‘utf8’)]
if_ name_=='_ main_ ':
httpd : make_server(‘’, 8080, demo_app):
sa = httpd.socket. getsockname()
print("Serving HTTP on", sa[0], "port", sa[1], "...")
import webbrowser
webbrowser .open( ' http://localhost : 8000/xyz?abc')
httpd.serve_forever() # serve one request, then exit
运行发现还是报错,return [‘hello’.encode(‘utf8’)] 是浏览器显示的内容,在此之前必须调一下 start_response 这个方法,这个方法不是我们传的,在server_forever 会自动调。
from wsgiref.simple_server import make_server
def demo_app(environ,start_response):
start_response(‘200 OK’,[(‘Content-Type,’text/html;charset=utf8’)])
return [‘hello’.encode(‘utf8’)]
if_ name_=='_ main_ ':
httpd : make_server(‘’, 8080, demo_app):
sa = httpd.socket. getsockname()
print("Serving HTTP on", sa[0], "port", sa[1], "...")
import webbrowser
webbrowser .open( ' http://localhost : 8000/xyz?abc')
httpd.serve_forever() # serve one request, then exit
运行以后就可以看到 hello
这就是最简单的 WSGI 的接口服务器的写法。只不过参数有一些复杂,创建的时候需要 make_server 指定 ip 地址和端口号,demo_app 找一个函数来处理数据,请求看到的内容就是函数做的。
4.start_response 的使用
start_response 也是一个函数,这个函数处理的时候会自动选参,里面要写状态码和响应头。再加一个头,写成:
start_response(‘200 OK’,[(‘Content-Type,’text/html;charset=utf8’),(’server’,’WSGI’)])
运行就可以在控制栏的 network 里看到:
加个响应头,自己随便写一个:
start_response(‘200 OK’,[(‘Content-Type,’text/html;charset=utf8’),(‘sss’, ‘ddd’)])
return [‘你好’.encode(‘utf8’)]
把端口改成 8090
如果怕自己访问到之前的缓存数据,可以右击在更多工具里清楚缓存,最保险的方法是换个端口。
运行以后就可以查看到自己写的头了,如下图。
5.environ 的作用
有同学会发现一个问题:environ 是不是没有作用
打印一下 environ:
from wsgiref.simple_server import make_server
def demo_app(environ,start_response):
print(environ)
start_response(‘200 OK’,[(‘Content-Type,’text/html;charset=utf8’)])
return [‘hello’.encode(‘utf8’)]
if_ name_=='_ main_ ':
httpd : make_server(‘’, 8080, demo_app):
sa = httpd.socket. getsockname()
print("Serving HTTP on", sa[0], "port", sa[1], "...")
import webbrowser
webbrowser .open( ' http://localhost : 8000/xyz?abc')
httpd.serve_forever() # serve one request, then exit
运行一下就会接收到数据
environ 是一个字典,保存了很多的数据,其中重要的一个是 PATH_INFO 能够获取用户的访问路径。它会列出访问网站时访问者带的一堆的环境。比如,用户的家目录,请求路径,参数 abc 等等。
如果想要拿到用户的请求路径,就可以写
path=environ[‘PATH_INFO’]
,不需要我们再切了。
from wsgiref.simple_server import make_server
def demo_app(environ,start_response):
path=environ[‘PATH_INFO’]
print(‘path={}’.format(path))
start_response(‘200 OK’,[(‘Content-Type,’text/html;charset=utf8’)])
return [‘hello’.encode(‘utf8’)]
if_ name_=='_ main_ ':
httpd : make_server(‘’, 8080, demo_app):
sa = httpd.socket. getsockname()
print("Serving HTTP on", sa[0], "port", sa[1], "...")
import webbrowser
webbrowser .open( ' http://localhost : 8000/xyz?abc')
httpd.serve_forever() # serve one request, then exit
运行一下
访问127.0.0.1:8080/demo
就会返回消息: