09 基于模块wsgiref版web框架
09 基于模块wsgiref版web框架
模块引入
真实开发中的python web程序,一般会分为两部分:
服务器程序:负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理;
应用程序:负责具体的逻辑处理。
为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。
这样,服务器程序就需要为不同的框架提供不同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。
正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口协议来实现这样的服务器软件,让我们专心用Python编写Web业务。
这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器。
WSGI(Web Server Gateway Interface)就是一种规范,它定义了使用Python编写的web应用程序与web服务器程序之间的接口格式,实现web应用程序与web服务器程序间的解耦。
常用的WSGI服务器有uwsgi、Gunicorn。而Python标准库提供的独立WSGI服务器叫wsgiref,Django开发环境用的就是这个模块来做服务器。
服务器server端python程序(wsgiref模版):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from wsgiref.simple_server import make_server 2 3 4 5 def application(environ,start_response): 6 7 """ 8 9 wsgiref.simple_server模块中的make_server方法调用的函数 10 11 :param environ: wsgiref模块中封装好的包含http请求所有信息的字典 12 13 :param start_response: wsgiref提供的内置方法(用于响应格式的发送) 14 15 :return:返回给浏览器的信息(以[]包装的bytes类型) 16 17 """ 18 19 # environ变量是模块自行封装好的http请求信息,以键值对的形式存在,可以直接字典取值 20 21 print(environ) 22 23 print(environ["PATH_INFO"]) # 打印请求的文件路径 24 25 print(environ["REQUEST_METHOD"]) # 打印请求的方式 26 27 28 29 # 服务端响应格式信息(状态信息和请求头部) 30 31 start_response("200 OK",[("Content-Type","text/html")]) 32 33 34 35 return [b'<h1>hello</h1>'] # 服务端返回数据用[]包装起来 36 37 38 39 #进行bind端口绑定、listen监听、封装http请求信息、 40 41 # 调用application函数(自动传递封装好的请求信息字典和wsgiref模块内置的响应格式发送函数) 42 43 htttpd=make_server("127.0.0.1",8888,application) 44 45 htttpd.serve_forever() #accept获取客户端端的连接,开启线程、发送服务端的返回信息
wsgiref模块:
将http请求封装成以键值对的形式封装成字典environ:
"PATH_INFO"对应的值为请求文件路径,
“QUERY_STRING”对应的值为get请求发送的数据
“REQUEST+METHOD”对应的值为请求方式。
同时封装一个发送响应格式的函数start_server;
通过特定的方式return [ ]返回数据并调用内置方法返回给浏览器。
客户端浏览器访问:
在浏览器地址栏直接输入地址端口:127.0.0.1:8888
基于wsgiref模块返回网页实例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 from wsgiref.simple_server import make_server 2 3 4 5 def func_html(): 6 7 with open("index.html","rb")as f: 8 9 return f.read() 10 11 def func_ico(): 12 13 with open("favicon.ico","rb")as f: 14 15 return f.read() 16 17 18 19 # make_sever自动调用的方法 20 21 def application(environ,start_response): 22 23 # 从封装好的请求信息字典找到请求文件路径 24 25 path = environ["PATH_INFO"] 26 27 # 发送响应信息(状态、响应头部信息可有可无) 28 29 start_response("200 OK",[("Content-Type","text/html")]) 30 31 # data表示要返回给浏览器的数据信息 32 33 for mapper in func_mappers: 34 35 if path == mapper[0]: 36 37 data=mapper[1]() 38 39 break 40 41 else: 42 43 data=b"Sorry:404 not find" 44 45 # 固定格式返回 46 47 return [data] 48 49 50 51 52 53 # 请求文件路径对应的返回数据读取操作映射 54 55 func_mappers=[ 56 57 ("/",func_html), 58 59 ("/favicon.ico",func_ico) 60 61 ] 62 63 64 65 # 程序启动位置: 66 67 httpd=make_server("127.0.0.1",8888,application) 68 69 httpd.serve_forever()
实例相关文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 <!DOCTYPE html> 2 3 <html lang="en"> 4 5 <head> 6 7 <meta charset="UTF-8"> 8 9 <link rel="icon" href="favicon.ico"> 10 11 <style> 12 13 span{ 14 15 background-color: yellow; 16 17 color: red; 18 19 font-size: 20px 20 21 } 22 23 </style> 24 25 <title>动态页面</title> 26 27 </head> 28 29 <body> 30 31 <div> 32 33 <h1>本次访问时间为: 34 35 <span>#time#</span> 36 37 </h1> 38 39 </div> 40 41 </body> 42 43 </html>