Web Socket

所谓 Web 服务,本质上就是用户使用一个 socket 客户端(浏览器)去访问一个 socket 服务端。

下面是一个最基础的基于 socket 的 Python Web 服务端程序。

import socket

# 最简单的web程序
def handle_request(connection):
content = connection.recv(1024)
print(content)
connection.send(bytes("HTTP/1.1 200 OK\r\n\r\n".encode("utf-8")))
connection.send(bytes("hello, World!".encode("utf-8"))) def service():
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('127.0.0.1', 8000)
server.bind(server_address)
server.listen(5) while True:
connection, client_address = server.accept()
print(connection)
handle_request(connection)
connection.close() if __name__ == '__main__':
service()

WSGI (Web Server Gateway Interface)

上面的例子展示了 Web 的本质。

但是对于现实中的 Python Web 程序来说,一般服务端程序会分为两部分:

  • 服务器程序(用来接收、整理客户端发送的请求)
  • 应用程序(处理服务器程序传递过来的请求)

而在服务端开发应用程序时,我们会把常用的功能函数封装起来,这就是各种 Web 框架了。

Python 常见的 Web 框架有 Django,Flask,Tornado 等等。

不同的框架提供了不同程度和方式的封装,方便程序员在其上进行二次开发。

但是,服务器程序应用程序 需要相互配合才能给用户提供服务,因此我们需要制定一个标准,只要双方同时遵守这个标准,就可以相互配合了。

在 Python 中,这个标准就是 WSGI 了。

WSGI 是一种规范,它规定了服务器程序和应用程序各自使用的接口和功能,实现了二者的解耦。

Python 标准库提供的独立 WSGI 服务器称之为 wsgiref

from wsgiref.simple_server import make_server

def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return [bytes('<h1>Hello, World</h1>'.encode("utf-8")), b'42'] def run_server():
server = make_server("127.0.0.1", 8000, application)
server.serve_forever() if __name__ == '__main__':
run_server()

路径处理

上面的例子虽然实现了一个正常的服务端功能,但却有一个巨大的缺陷,那就是不同的 url 也只能返回相同的内容,为了解决这个问题,我们对代码作出如下修改。

from wsgiref.simple_server import make_server

def application(environ, start_response):
url = environ['PATH_INFO']
print("url:", url)
start_response('200 OK', [('Content-Type', 'text/html')])
if url == "/index":
return [bytes('<h1>index!</h1>'.encode("utf-8")), b'42']
elif url == "/login":
return [bytes('<h1>login !</h1>'.encode("utf-8")), b'42']
elif url == "/logout":
return [bytes('<h1>logout !</h1>'.encode("utf-8")), b'42']
else:
return [bytes('<h1>404 !</h1>'.encode("utf-8")), b'42'] def run_server():
server = make_server("127.0.0.1", 8000, application)
server.serve_forever() if __name__ == '__main__':
run_server()

通过从 environ 中获取存储着路径的变量 PATH_INFO。我们就可以对不同的 url 返回不同的结果了。

分层处理

上面的例子虽然做到了对不同的路径返回不同的结果,但是所有的逻辑都写在一个函数内,一旦体量增加就会混乱不堪。

因此我们需要对应用程序进行进一步的解耦。

from wsgiref.simple_server import make_server

def index():
return [bytes('<h1>index!</h1>'.encode("utf-8")), b'42'] def login():
return [bytes('<h1>login !</h1>'.encode("utf-8")), b'42'] def logout():
return [bytes('<h1>logout !</h1>'.encode("utf-8")), b'42'] urlConf = [
("/index", index),
("/login", login),
("/logout", logout),
] # 不同的网址有不同的结果,但是所有的处理逻辑写到一起,很混乱
def application(environ, start_response):
url = environ['PATH_INFO']
print("url:", url) response_fun = None for item in urlConf:
if url == item[0]:
response_fun = item[1]
break if response_fun:
start_response('200 OK', [('Content-Type', 'text/html')])
response_body = response_fun()
else:
start_response('404 Not Found', [('Content-Type', 'text/html')])
response_body = [bytes('<h1>404 !</h1>'.encode("utf-8")), b'42']
return response_body def run_server():
server = make_server("127.0.0.1", 8000, application)
server.serve_forever() if __name__ == '__main__':
run_server()



怎么样是不是已经有点像我们平时使用的各种框架了。

urlConf用户根据不同的路径,配置不同的函数。

server程序中遍历urlConf来根据路径定位所要执行的函数。

文件拆分

上面的例子已经有了框架的雏形了,但所有的功能都在一个 Python 文件中,很不优雅。

这时你就可以将代码分成三个文件。

view.py:专门用户存放各种页面的处理函数

url.py 配置路径和函数的关系

server.py 执行web的主程序

将不同功能的代码分门别类存放,进行进一步的解耦。

Python Web 框架原理的更多相关文章

  1. Django之web框架原理

    Web框架原理 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web框架了. 先写一个 原始的web框架 imp ...

  2. Werkzeug——python web开发工具包

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10826062.html 一:Werkzeug是个啥 1)Werkzeug是一个工具包,它封装了很多东西,诸如 ...

  3. Django安装和web框架原理

    Django安装和web框架原理 在PyCharm中安装 在cmd中输入 django-admin startproject 项目名 如果报错 不是内部或外部命令,也不是可运行的程序 需要添加环境变量 ...

  4. Redis的Python实践,以及四中常用应用场景详解——学习董伟明老师的《Python Web开发实践》

    首先,简单介绍:Redis是一个基于内存的键值对存储系统,常用作数据库.缓存和消息代理. 支持:字符串,字典,列表,集合,有序集合,位图(bitmaps),地理位置,HyperLogLog等多种数据结 ...

  5. Python Web 方向(一)

    Python Web 方向(一) --------Django站点创建 文章地址:http://www.cnblogs.com/likeli/p/5821744.html Python版本:2.7 推 ...

  6. 浅谈五大Python Web框架

    转载:http://feilong.me/2011/01/talk-about-Python-web-framework 说到Web Framework,Ruby的世界Rails一统江湖,而Pytho ...

  7. nginx上部署python web

    nginx上部署python web http://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html

  8. 全面解读python web 程序的9种部署方式

    转载自鲁塔弗的博客,本文地址http://lutaf.com/141.htm  python有很多web 开发框架,代码写完了,部署上线是个大事,通常来说,web应用一般是三层结构 web serve ...

  9. Python Web 开发的十个框架【转载】

    Python 是一门动态.面向对象语言.其最初就是作为一门面向对象语言设计的,并且在后期又加入了一些更高级的特性.除了语言本身的设计目的之外,Python标准 库也是值得大家称赞的,Python甚至还 ...

随机推荐

  1. AppBar 自定义顶部导航按钮 图标、颜色 以及 TabBar 定义顶部 Tab 切换

    一.Flutter AppBar 自定义顶部按钮图标.颜色 leading   在标题前面显示的一个控件,在首页通常显示应用的 logo:在其他界面通常显示为返回按钮 title  标题,通常显示为当 ...

  2. 基于SILVACO ATLAS的a-IGZO薄膜晶体管二维器件仿真(06)

    在知网看到了江南大学的硕士论文: 双有源层a-IGZO薄膜晶体管的特性仿真 IGZO/IZO双有源层薄膜晶体管特性的模拟研究 发现,我昨天的文章中参数的设置存在重大失误,如下材料定义语句中: mate ...

  3. idea 快捷使用(三)中断Debug的使用

    想要在Debug的时候,中断请求,不要再走剩余的流程了? 不需要关闭服务重新启动程序,可以通过Force Return,即强制返回来避免后续的流程. 点击Force Return,弹出Return V ...

  4. SEO 建站过程复盘

    今天在A5看到一篇关于一个牛站的复盘,整个建站过程值得借鉴. https://www.admin5.com/article/20200218/943930.shtml

  5. python之requests库使用

    requests库 虽然Python的标准库中 urllib模块已经包含了平常我们使用的大多数功能,但是它的 API 使用起来让人感觉不太好,而 Requests宣传是 “HTTP for Human ...

  6. ABC156E

    题目链接 也是简单的组合数学问题,每个位置可以移动走,也可以移动来,那么我们就需要找最终的状态,也就是最终的0的个数 假设有m个0,就有n-m个非0空位,选择0的组合数为\(\textrm{C}_{n ...

  7. 区块链学习——HyperLedger-Fabric v1.0 启动过程分析

    本章我们从fabric v1.0的e2e_cli示例开始分析整个启动过程以及在过程中的一些配置文件 首先呢,还是确保你的基本环境已经搭建完成,v1.0源码和镜像也都下载完毕 fabric启动过程中的相 ...

  8. python:字符串类型

    字符串概念 字符串:由单个字符组成的一个序列, 字符串是一个不可变的类型 形式: 非原始字符串: 单引号:单引号包起来的一段字符就是字符串 双引号:和单引号一样 三引号:三引号包括的字符串可以换行,保 ...

  9. Web Storage API:localStorage 和 SessionStorage

    Web Storage API 提供了存储机制,通过该机制,浏览器可以安全地存储键值对,比使用 cookie 更加直观. 参考:https://developer.mozilla.org/zh-CN/ ...

  10. python数组冒号取值操作

    1.冒号的用法 1.1 一个冒号 a[i:j] 这里的i指起始位置,默认为0:j是终止位置,默认为len(a),在取出数组中的值时就会从数组下标i(包括)一直取到下标j(不包括j) 在一个冒号的情况下 ...