前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深入浅出web服务器与python应用程序之间的联系

深入浅出web服务器与python应用程序之间的联系

作者头像
Ryan_OVO
发布2023-10-18 20:14:46
1200
发布2023-10-18 20:14:46
举报
文章被收录于专栏:程序随笔程序随笔

简单来说,Web服务器是在运行在物理服务器上的一个程序,它永久地等待客户端(主要是浏览器,比如Chrome,Firefox等)发送请求。Web 服务器接受 Http Request,返回 Response,很多时候 Response 并不是静态文件,因此需要有一个应用程序根据 Request 生成相应的 Response。这里的应用程序主要用来处理相关业务逻辑,读取或者更新数据库,根据不同 Request 返回相应的 Response。两者之间的桥梁就是WSGI。 一直喜欢研究比较底层的技术, 之前就对python web框架web.py的运行机制比较迷惑, 大概学习了下之后发现flask框架以及Django框架都是基于python WSGI协议, python提供了一个简易的wsgi服务器实现--wsgiref, 在网站上找了两个例子运行了一下, 讲真, 第一次运行起来就比较懵逼, 尽管知道底层是依赖于socket, 但是深入一点就没有再研究了, 也看不懂。于是花了几天, 踏踏实实的看了源码, 一边百度一边理解, 终于学到了很多。有时候觉得自己让asp.net"惯坏"了, 因为微软闭源的关系, 自己掌握的基础知识并不全, 在很多的框架使用上, 仅仅会, 原理说个三三四四的, 还是差了很多, 果然开源就是好, 一言不合攻源码, 的确是学到了很多, python也是个很强大的语言, 这是我阅读其源码最大的感受。 讲真, 在没有读这两篇文章之前, 尽管我对web服务器, web框架有了解, 但还是比较模糊, 这两篇文章写的很好。伯乐在线也是个不错的技术网站! 阅读完这两篇文章后, 那就有一定的基础了。先上代码:

代码语言:javascript
复制
 # main.py
 1 # coding: utf-8
 2 import time
 3 from resty import PathDispatcher
 4 from wsgiref.simple_server import make_server
 5 
 6 
 7 _hello_resp = '''\
 8 <html>
 9   <head>
10      <title>Hello {name}</title>
11    </head>
12    <body>
13      <h1>Hello {name}!</h1>
14    </body>
15 </html>'''
16 
17 
18 def hello_world(environ, start_response):
19     # 将响应状态和响应头交给WSGI server
20     # from wsgiref.handlers import SimpleHandler
21     start_response('200 OK', [('Content-type', 'text/html')])
22     params = environ['params']
23     resp = _hello_resp.format(name=params.get('name'))
24     yield resp.encode('utf-8')
25 
26 
27 _localtime_resp = '''\
28 <?xml version="1.0"?>
29 <time>
30   <year>{t.tm_year}</year>
31   <month>{t.tm_mon}</month>
32   <day>{t.tm_mday}</day>
33   <hour>{t.tm_hour}</hour>
34   <minute>{t.tm_min}</minute>
35   <second>{t.tm_sec}</second>
36 </time>'''
37 
38 
39 def localtime(environ, start_response):
40     # 将响应状态和响应头交给WSGI server
41     start_response('200 OK', [('Content-type', 'application/xml')])
42     resp = _localtime_resp.format(t=time.localtime)
43     yield resp.encode('utf-8')
44 
45 
46 # 模拟客户端
47 if __name__ == '__main__':
48     dispatcher = PathDispatcher()
49     dispatcher.register('GET', '/hello', hello_world)
50     dispatcher.register('GET', '/localtime', localtime)
51 
52     # 启动一个简易的服务器
53     httpd = make_server('', 8080, dispatcher)
54     print "Serving on port 8080..."
55     httpd.serve_forever()  # 开启循环机制
代码语言:javascript
复制
 # resty.py
 1 # coding: utf-8
 2 import cgi
 3 
 4 
 5 def notfound_404(environ, start_response):
 6     start_response('404 Not Found', [('Content-type', 'text/plain')])
 7     return ['Not Found']
 8 
 9 
10 # 使用了中间件
11 class PathDispatcher:
12     def __init__(self):
13         self.pathmap = {}
14 
15     # 使此类的对象具有函数的能力, 对象能够接受传参, 就像函数调用一样, 此函数在handlers.py 中调用
16     def __call__(self, environ, start_response):
17         path = environ['PATH_INFO']
18         params = cgi.FieldStorage(environ['wsgi.input'], environ=environ)
19 
20         method = environ['REQUEST_METHOD'].lower()
21         environ['params'] = {key: params.getvalue(key) for key in params}  # 字典推导式
22         handler = self.pathmap.get((method, path), notfound_404)
23         return handler(environ, start_response)
24 
25     def register(self, method, path, function):
26         self.pathmap[method.lower(), path] = function
27         return function

然后我分析下python自带的wsgi服务器主要文件的作用:

simple_server.py模拟了一个简单的web服务器, handlers.py是wsgi协议对http协议的封装处理函数。看下图吧:

如上所示, 我大概归纳了一下不同py文件的作用。我之前对WSGI的作用比较模糊, 尽管知道WSGI就是连接web服务器与web应用程序之间的桥梁, 但是讲真!在客户端浏览器敲入换行后, python应用程序的具体执行了哪些重要的函数, 其调用顺序又是怎么来的。而且看着上面的代码,我问你一个问题: __call__函数是啥时候调用的?在程序里面你看见了__call__的调用吗?尽管__call__函数是一个内置函数(我对其做了注释), 已经有了定义, 现在又有了实现代码, 那么调用程序呢? 原谅作为一个工科生的牛角尖, 看到程序里面有不明不白的调用实在憋屈-.- 看完下面的, 你应该就懂了

好好把<<从零开始搭建论坛(2):Web服务器网关接口>>看完, 同时要弄明白__call __函数的作用。不过, 我先来解释下吧, 全程debug给你看看:

/////////////编程环境: win7  ////////// IDE: VS code   ///////python version: 2.7.13 我分别在main.py, handlers, resty.py下了断点, 开始debug把....

当调试控制台出现 "Serving on port 8080..." 表示此时等待客户端浏览器的访问了, 下面, 我们在浏览器中写入 http://127.0.0.1:8080/hello?name=Ryan

图15注意下envron变量的值, 这就是一个dict类型的变量, 可以看到, 我们在浏览器中的 "?"后面的key-value都给保存进来了。传给了python应用程序。 当然, 要完成一个完整的url访问肯定不止这些函数模块的调用, 这就是主要的调用而已, 而且这已经很好的解释了我之前的问题了, 好了, 根据图自己去理解吧

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-09-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
消息队列 TDMQ
消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档