Python 第五阶段 学习记录之--- Web框架
Web框架本质
众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。
- #!/usr/bin/env python
- #coding:utf-8
- import socket
- def handle_request(client):
- buf = client.recv(1024)
- client.send("HTTP/1.1 200 OK\r\n\r\n")
- client.send("Hello, Seven")
- def main():
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- sock.bind(('localhost',8000))
- sock.listen(5)
- while True:
- connection, address = sock.accept()
- handle_request(connection)
- connection.close()
- if __name__ == '__main__':
- main()
上述通过socket来实现了其本质,而对于真实开发中的python web程序来说,一般会分为两部分:服务器程序和应用程序。服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理。应用程序则负责具体的逻辑处理。为了方便应用程序的开发,就出现了众多的Web框架,例如:Django、Flask、web.py 等。不同的框架有不同的开发方式,但是无论如何,开发出的应用程序都要和服务器程序配合,才能为用户提供服务。这样,服务器程序就需要为不同的框架提供不同的支持。这样混乱的局面无论对于服务器还是框架,都是不好的。对服务器来说,需要支持各种不同框架,对框架来说,只有支持它的服务器才能被开发出的应用使用。这时候,标准化就变得尤为重要。我们可以设立一个标准,只要服务器程序支持这个标准,框架也支持这个标准,那么他们就可以配合使用。一旦标准确定,双方各自实现。这样,服务器可以支持更多支持标准的框架,框架也可以使用更多支持标准的服务器。
WSGI(Web Server Gateway Interface)是一种规范,它定义了使用python编写的web app与web server之间接口格式,实现web app与web server间的解耦。
python标准库提供的独立WSGI服务器称为wsgiref。
- from wsgiref.simple_server import make_server
- def RunServer(environ, start_response):
- start_response('200 OK', [('Content-Type', 'text/html')])
- return [bytes('<h1>Hello, web!</h1>', encoding='utf-8'), ]
- if __name__ == '__main__':
- httpd = make_server('', 8000, RunServer)
- print("Serving HTTP on port 8000...")
- httpd.serve_forever()
自定义Web框架
一、框架
通过python标准库提供的wsgiref模块开发一个自己的Web框架
- #!/usr/bin/env python
- #coding:utf-8
- from wsgiref.simple_server import make_server
- def index():
- return 'index'
- def login():
- return 'login'
- def routers():
- urlpatterns = (
- ('/index/',index),
- ('/login/',login),
- )
- return urlpatterns
- def RunServer(environ, start_response):
- start_response('200 OK', [('Content-Type', 'text/html')])
- url = environ['PATH_INFO']
- urlpatterns = routers()
- func = None
- for item in urlpatterns:
- if item[0] == url:
- func = item[1]
- break
- if func:
- return func()
- else:
- return '404 not found'
- if __name__ == '__main__':
- httpd = make_server('', 8000, RunServer)
- print "Serving HTTP on port 8000..."
- httpd.serve_forever()
2、模板引擎
在上一步骤中,对于所有的login、index均返回给用户浏览器一个简单的字符串,在现实的Web请求中一般会返回一个复杂的符合HTML规则的字符串,所以我们一般将要返回给用户的HTML写在指定文件中,然后再返回。如:
- <!DOCTYPE html>
- <html>
- <head lang="en">
- <meta charset="UTF-8">
- <title></title>
- </head>
- <body>
- <h1>Index</h1>
- </body>
- </html>
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- from wsgiref.simple_server import make_server
- def index():
- # return 'index'
- f = open('index.html')
- data = f.read()
- return data
- def login():
- # return 'login'
- f = open('login.html')
- data = f.read()
- return data
- def routers():
- urlpatterns = (
- ('/index/', index),
- ('/login/', login),
- )
- return urlpatterns
- def run_server(environ, start_response):
- start_response('200 OK', [('Content-Type', 'text/html')])
- url = environ['PATH_INFO']
- urlpatterns = routers()
- func = None
- for item in urlpatterns:
- if item[0] == url:
- func = item[1]
- break
- if func:
- return func()
- else:
- return '404 not found'
- if __name__ == '__main__':
- httpd = make_server('', 8000, run_server)
- print "Serving HTTP on port 8000..."
- httpd.serve_forever()
对于上述代码,虽然可以返回给用户HTML的内容以现实复杂的页面,但是还是存在问题:如何给用户返回动态内容?
- 自定义一套特殊的语法,进行替换
- 使用开源工具jinja2,遵循其指定语法
- <!DOCTYPE html>
- <html>
- <head lang="en">
- <meta charset="UTF-8">
- <title></title>
- </head>
- <body>
- <h1>{{name}}</h1>
- <ul>
- {% for item in user_list %}
- <li>{{item}}</li>
- {% endfor %}
- </ul>
- </body>
- </html>
index.html
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- from wsgiref.simple_server import make_server
- from jinja2 import Template
- def index():
- # return 'index'
- # template = Template('Hello {{ name }}!')
- # result = template.render(name='John Doe')
- f = open('index.html')
- result = f.read()
- template = Template(result)
- data = template.render(name='John Doe', user_list=['alex', 'eric'])
- return data.encode('utf-8')
- def login():
- # return 'login'
- f = open('login.html')
- data = f.read()
- return data
- def routers():
- urlpatterns = (
- ('/index/', index),
- ('/login/', login),
- )
- return urlpatterns
- def run_server(environ, start_response):
- start_response('200 OK', [('Content-Type', 'text/html')])
- url = environ['PATH_INFO']
- urlpatterns = routers()
- func = None
- for item in urlpatterns:
- if item[0] == url:
- func = item[1]
- break
- if func:
- return func()
- else:
- return '404 not found'
- if __name__ == '__main__':
- httpd = make_server('', 8000, run_server)
- print "Serving HTTP on port 8000..."
- httpd.serve_forever()
动态内容
遵循jinja2的语法规则,其内部会对指定的语法进行相应的替换,从而达到动态的返回内容,对于模板引擎的本质那又是什么?
** 下回分解
Python 第五阶段 学习记录之--- Web框架的更多相关文章
- Python 第五阶段 学习记录之---Django 基础
Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能. ...
- Python 第五阶段 学习记录之---Django 进阶
Model 一.创建表 1.基本结构 字段 AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bi ...
- Python 第五阶段 学习记录之----ORM
ORM: orm英文全称object relational mapping,就是对象映射关系程序,简单来说我们类似python这种面向对象的程序来说一切皆对象,但是我们使用的数据库却都是关系型的,为了 ...
- Python 第五阶段 学习记录之----rabbmit
消息服务器rabbmit RabbitMQ 消息队列 python里有两个Q, threading queue.不同线程间数据交互 进程Queue: 不同进程间交互这个说法是错误的. 这个是用于父进程 ...
- Python 第八阶段 学习记录之---算法
算法(Algorithm): 一个计算过程, 解决问题的方法 1.递归的两个特点 - 调用自身 - 结束条件 时间复杂度 - 时间复杂度是用来估计算法运行时间的一个式子(单位) - 一般来说,时间复杂 ...
- python 第四阶段 学习记录之----异步
异步: 知识情况: 1.多线程, 多线程使用场景 1.IO操作不占CPU,读写数据(网络中.系统中) 2.计算占CPU, 3.上下文切换不占CPU.它消耗资源 python多线程 不适合CPU密集型的 ...
- Python 第四阶段 学习记录之----多线程
多线程 多线程例子, 注释部份即为多线程的使用 #-*- coding: utf-8 -*- # Wind clear raise # 2017/3/5 下午2:34 import socket im ...
- go语言,golang学习笔记2 web框架选择
go语言,golang学习笔记2 web框架选择 用什么go web框架比较好呢?能不能推荐个中文资料多的web框架呢? beego框架用的人最多,中文资料最多 首页 - beego: 简约 & ...
- [Python之路] 使用装饰器给Web框架添加路由功能(静态、动态、伪静态URL)
一.观察以下代码 以下来自 Python实现简易HTTP服务器与MINI WEB框架(利用WSGI实现服务器与框架解耦) 中的mini_frame最后版本的代码: import time def in ...
随机推荐
- 框架源码系列七:Spring源码学习之BeanDefinition源码学习(BeanDefinition、Annotation 方式配置的BeanDefinition的解析)
一.BeanDefinition 1. bean定义都定义了什么? 2.BeanDefinition的继承体系 父类: AttributeAccessor: 可以在xml的bean定义里面加上DTD ...
- YARN 启动后失败退出——没有请求资源——Invalid resource request, no resources request
在ambari-server中修改了yarn的配置,重新启动服务,结果RM启动失败,错误也很奇怪,“不合理的资源请求,没有请求任何资源”!详细如下: -- ::, FATAL resourcemana ...
- ABBYY PDF Transformer+支持的格式
ABBYY PDF Transformer+是一个新的,全面的巧妙解决PDF文档的工具,它将泰比的光学字符识别(OCR)技术和Adobe®PDF技术完美结合,以确保实现便捷地处理任何类型的PDF文件, ...
- 最强Android书 架构大剖析 作者网站
http://newandroidbook.com/ jonathan levin (最强Android书 架构大剖析) http://newandroidbook.com/AIvI-M-R ...
- 【CF666E】Forensic Examination 广义后缀自动机+倍增+线段树合并
[CF666E]Forensic Examination 题意:给你一个字符串s和一个字符串集合$\{t_i\}$.有q个询问,每次给出$l,r,p_l,p_r$,问$s[p_l,p_r]$在$t_l ...
- 最新版本sublime text3注册码
TwitterInc 200 User License EA7E-890007 1D77F72E 390CDD93 4DCBA022 FAF60790 61AA12C0 A37081C5 D03164 ...
- E - Stones 优先队列
来源1896 Because of the wrong status of the bicycle, Sempr begin to walk east to west every morning an ...
- Dijkstra模板
Dijkstra struct node { long long x,d; node(); node(long long xx,long long dd){ x = xx; d = dd; } }; ...
- [ERROR] - Error reading string. Unexpected token: StartObject. Path 'formData', line 1, position 13.
公司流程框架: businessData 为 string 所有要使用JSON.stringify();
- php const常量 不能使用字符串连接符.链接
class jdpay extends pay { const BASE_URL = "https://mapi.jdpay.com/npp10/"; private $agree ...