Web框架的引入

为什么会有web框架

有了上一篇内容,静态、动态web服务器的实现,已经掌握了客户端请求到服务器处理的机制。在动态资源处理中,根据请求 .py 导入模块应用,然后调用应用入口程序实现动态处理。但是在真实的项目中,肯定有很多应用(.py文件),按照这种处理机制(每个应用中都要写一个入口,设置状态码、headers)不符合架构设计原则,这一部分肯定是可以复用的,所用应用应该公用一个入口,这就引入一个概念web框架。

设计思路

  • 把每个应用中入口 application(env,start_response) 提取到web服务器中,然后在入口中通过路由机制分发到各应用中处理。

代码如下:

- WebFramework.py

`
# coding:utf-8

import time
from MyWebServer import WebServer

HTML_ROOT_DIR = "./static"

class Application(object):
    ‘‘‘自定义通用的web框架‘‘‘

    # 初始化路由信息
    def __init__(self,urls):
        self.urls = urls

    # 匹配路由
    def __call__(self, env, start_response):
        path = env.get("PATH_INFO", "/")
        # /static/index.html
        if path.startswith("/static"):
            file_name = path[7:]
            # 打开文件,读取内容
            try:
                file = open(HTML_ROOT_DIR + file_name, "rb")
            except IOError:
                # 代表未找到路由信息,404错误
                status = "404 Not Found"
                headers = []
                start_response(status, headers)
                return "not found"
            else:
                file_data = file.read()
                file.close()

                status = "200 OK"
                headers = []
                start_response(status, headers)
                return file_data.decode("utf-8")

        for url,handler in self.urls:
            if path == url:
                return handler(env,start_response)
        # 未匹配到
        status = ‘404 Not Found‘
        headers = []
        start_response(status,headers)
        return ‘not found‘

def showtime(env,start_response):
    status = ‘200 OK‘
    headers = [
        (‘Content-Type‘, ‘text/plain‘)
    ]
    start_response(status, headers)
    return str(time.time())

def sayhello(env,start_response):
    status = ‘200 OK‘
    headers = [
        (‘Content-Type‘,‘text/plain‘)
    ]
    start_response(status,headers)
    return ‘say hello‘

def helloworld(env,start_response):
    status = ‘200 OK‘
    headers =[
        (‘Content-Type‘,‘text/plain‘)
    ]
    start_response(status,headers)
    return ‘hello world‘

if __name__ == ‘__main__‘:
    urls = [
        (‘/‘, showtime),
        (‘/sayhello‘,sayhello),
        (‘/helloworld‘,helloworld)
    ]
    app = Application(urls)

    webServer = WebServer(app)
    webServer.bind(8000)
    webServer.start()

`

- MyWebServer.py

`
# coding:utf-8

import socket
import re
import sys

from multiprocessing import Process

HTML_ROOT_DIR = ‘./static‘
WSGI_PY = ‘./wsgipy‘

class WebServer(object):
    ‘‘‘
    简单的webserver
    ‘‘‘

    def __init__(self,application):
        ‘‘‘application:框架‘‘‘
        self.sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.app = application

    def start(self):
        self.sock_server.listen(128)
        while True:
            sock_client, addr = self.sock_server.accept()
            print(‘[%s,%s]用户已连接......‘ % addr)
            handle_client_process = Process(target=self.handle_client, args=(sock_client,))
            handle_client_process.start()
            sock_client.close()

    def start_response(self, status, headers):
        """
                 status = "200 OK"
            headers = [
                ("Content-Type", "text/plain")
            ]
            star
                """
        resp_headers = ‘HTTP/1.1 ‘ + status + ‘\r\n‘
        for header in headers:
            resp_headers += ‘%s: %s\r\n‘ % header

        self.resp_headers = resp_headers

    def handle_client(self, sock_client):
        ‘‘‘处理客户端请求‘‘‘
        recv_data = sock_client.recv(1024)
        #print(‘请求数据:‘, recv_data)
        req_lines = recv_data.splitlines()
        #for line in req_lines:
        #    print(line)

        req_start_line = req_lines[0]
        #print(req_start_line.decode(‘utf-8‘))
        file_name = re.match(r"\w+ +(/[^ ]*) ", req_start_line.decode("utf-8")).group(1)
        method = re.match(r"(\w+) +/[^ ]* ", req_start_line.decode("utf-8")).group(1)

        env = {
            "PATH_INFO": file_name,
            "METHOD": method
        }
        response_body = self.app(env, self.start_response)

        response = self.resp_headers + "\r\n" + response_body

        # 向客户端返回响应数据
        sock_client.send(bytes(response, "utf-8"))

        # 关闭客户端连接
        sock_client.close()

    def bind(self, port):
        self.sock_server.bind((‘‘, port))

def main():
    sys.path.insert(1,WSGI_PY)
    webServer = WebServer()
    webServer.bind(8000)
    webServer.start()

if __name__ == ‘__main__‘:
    main()

`

启动

入口实在WebFramework.py 中,直接启动该文件,客户端请求指定路径即可看到效果。但是对于大多框架都是通过命令行启动,我们不可能在程序中这样启动,而且对于webserver来说始终是不变得,变的是web框架,所以改造成命令行启动,代码如下:

- WebFramework.py

`
# coding:utf-8

import time

HTML_ROOT_DIR = "./static"

class Application(object):
    ‘‘‘自定义通用的web框架‘‘‘

    # 初始化路由信息
    def __init__(self,urls):
        self.urls = urls

    # 匹配路由
    def __call__(self, env, start_response):
        path = env.get("PATH_INFO", "/")
        # /static/index.html
        if path.startswith("/static"):
            file_name = path[7:]
            # 打开文件,读取内容
            try:
                file = open(HTML_ROOT_DIR + file_name, "rb")
            except IOError:
                # 代表未找到路由信息,404错误
                status = "404 Not Found"
                headers = []
                start_response(status, headers)
                return "not found"
            else:
                file_data = file.read()
                file.close()

                status = "200 OK"
                headers = []
                start_response(status, headers)
                return file_data.decode("utf-8")

        for url,handler in self.urls:
            if path == url:
                return handler(env,start_response)
        # 未匹配到
        status = ‘404 Not Found‘
        headers = []
        start_response(status,headers)
        return ‘not found‘

def showtime(env,start_response):
    status = ‘200 OK‘
    headers = [
        (‘Content-Type‘, ‘text/plain‘)
    ]
    start_response(status, headers)
    return str(time.time())

def sayhello(env,start_response):
    status = ‘200 OK‘
    headers = [
        (‘Content-Type‘,‘text/plain‘)
    ]
    start_response(status,headers)
    return ‘say hello‘

def helloworld(env,start_response):
    status = ‘200 OK‘
    headers =[
        (‘Content-Type‘,‘text/plain‘)
    ]
    start_response(status,headers)
    return ‘hello world‘

urls = [
    (‘/‘, showtime),
    (‘/sayhello‘,sayhello),
    (‘/helloworld‘,helloworld)
]
app = Application(urls)
# if __name__ == ‘__main__‘:
#     urls = [
#         (‘/‘, showtime),
#         (‘/sayhello‘,sayhello),
#         (‘/helloworld‘,helloworld)
#     ]
#     app = Application(urls)
#
#     webServer = WebServer(app)
#     webServer.bind(8000)
#     webServer.start()
`

- MyWebServer.py

`
# coding:utf-8

import socket
import re
import sys

from multiprocessing import Process

HTML_ROOT_DIR = ‘./static‘
WSGI_PY = ‘./wsgipy‘

class WebServer(object):
    ‘‘‘
    简单的webserver
    ‘‘‘

    def __init__(self,application):
        ‘‘‘application:框架‘‘‘
        self.sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.app = application

    def start(self):
        self.sock_server.listen(128)
        while True:
            sock_client, addr = self.sock_server.accept()
            print(‘[%s,%s]用户已连接......‘ % addr)
            handle_client_process = Process(target=self.handle_client, args=(sock_client,))
            handle_client_process.start()
            sock_client.close()

    def start_response(self, status, headers):
        """
                 status = "200 OK"
            headers = [
                ("Content-Type", "text/plain")
            ]
            star
                """
        resp_headers = ‘HTTP/1.1 ‘ + status + ‘\r\n‘
        for header in headers:
            resp_headers += ‘%s: %s\r\n‘ % header

        self.resp_headers = resp_headers

    def handle_client(self, sock_client):
        ‘‘‘处理客户端请求‘‘‘
        recv_data = sock_client.recv(1024)
        #print(‘请求数据:‘, recv_data)
        req_lines = recv_data.splitlines()
        #for line in req_lines:
        #    print(line)

        req_start_line = req_lines[0]
        #print(req_start_line.decode(‘utf-8‘))
        file_name = re.match(r"\w+ +(/[^ ]*) ", req_start_line.decode("utf-8")).group(1)
        method = re.match(r"(\w+) +/[^ ]* ", req_start_line.decode("utf-8")).group(1)

        env = {
            "PATH_INFO": file_name,
            "METHOD": method
        }
        response_body = self.app(env, self.start_response)

        response = self.resp_headers + "\r\n" + response_body

        # 向客户端返回响应数据
        sock_client.send(bytes(response, "utf-8"))

        # 关闭客户端连接
        sock_client.close()

    def bind(self, port):
        self.sock_server.bind((‘‘, port))

def main():
    sys.path.insert(1,WSGI_PY)
    if len(sys.argv) < 2:
        sys.exit("python MyWebServer.py Module:app")
    module_name, app_name = sys.argv[1].split(‘:‘)
    m = __import__(module_name)
    app = getattr(m,app_name)
    webServer = WebServer(app)
    webServer.bind(8000)
    webServer.start()

if __name__ == ‘__main__‘:
    main()
`

调用方式

在命令行中,执行如下命令即可启动webserver服务,模块名称:应用框架名, 其中这里的app指的是WebFramework.py中Application类的实例,其实也就是应用框架的实例。后续自定义框架的时候,直接调用即可。

`
python MyWebServer.py WebFramework:app
`

代码已上传到github:python 小程序

时间: 2024-10-27 03:48:52

Web框架的引入的相关文章

13.python中web框架概念的引入。

一.什么是web框架? 框架,就是一个为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演. 对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. 最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回. 如果要动态生成HTML,就需要把上述步骤自己来实现.不过,接受HTTP请求.解析HTTP请求.发

在Java Web项目中引入Mondrian多维分析框架

一,Mondrian简介 Mondrian是一个开源项目,一个用Java写成的OLAP引擎.它用MDX语言实现查询,从关系数据库(RDBMS)中读取数据.然后经过Java API以多维的方式对结果进行展示. Mondrian的使用方式同JDBC驱动类似.可以非常方便的与现有的Web项目集成. Mondrian OLAP 系统由四个层组成,可分为从最终用户到数据中心, 顺序为: 1表现层(the presentation layer) 2维度层(the dimensional layer) 3集合

Python开发【第二十二篇】:Web框架之Django【进阶】

Python开发[第二十二篇]:Web框架之Django[进阶] 猛击这里:http://www.cnblogs.com/wupeiqi/articles/5246483.html 博客园 首页 新随笔 联系 订阅 管理 随笔-124  文章-127  评论-205 Python之路[第十七篇]:Django[进阶篇 ] Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻

python运维开发(十七)----jQuery续(示例)web框架django

内容目录: jQuery示例 前端插件 web框架 Django框架 jQuery示例 dom事件绑定 jQuery事件绑定 jQuery循环break jQuery扩展方法 jQuery自定义扩展的方法 jquery扩展实现基本验证 支持是否为空 长度 正则表达式 定义正则表达式 reg = /正则表达式/ ***** g i m ==> 特殊 利用正则匹配 reg.test(字符串) ***** reg.exec(字符串) 全局 非全局字符串三个方法: search match replac

python 全栈 web框架 Django基本操作

django 操作总结! django框架安装: cmd安装: pip3 install django pycharm安装: 在python变量下 搜索 django 安装 创建django项目: cmd下创建django项目: 创建django程序: django-admin startproject mysite 进入程序目录: cd mysite 启动socket服务端,等待用户发送请求 IP 端口 python manage.py runserver 127.0.0.1:8080 pyc

python_way day17 前段插件(fontawsome,easyui,bootstrap,jqueryui,bxslider,jquerylazyload),web框架

python_way day17 一.模板插件 图标的插件 fontawsome: 后台管理: easyui jqueryui 很多网站都会用: bootstrap :引入jQuery:(2.x,1.1.) :引入js bootstrap模板: bootstrap后台管理模板: bxslider:轮播图 jquerylazyload:延迟加载,所有的图片延迟加载 http://www.cnblogs.com/wupeiqi/articles/5813161.html faulure_limit:

python开发学习-day15(前端部分知识、web框架、Django创建项目)

s12-20160430-day15 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* BLOCKS =============================================================================*/ p, blockquote, ul, ol, dl, table, pre { margin

python web框架分析和学习篇_彭友

分析篇: 刚好到网上搜到了一篇<浅谈Python web框架>,里面系统的分析了五种主流的Python框架,现在python的主流框架有Django.Pylons&TurboGears&repose.bfg.Tornado&web.py&Bottle&Flask和Quixote.它从宏观角度分析了这五种框架的优劣,看完之后我们决定选择Django,因为: Django: 概述:可谓是python框架里面最大的一家,它是里面文档最完善.市场占有率最高.招聘

基于servlet实现一个web框架

servlet作为一个web规范.其本身就算做一个web开发框架,可是其web action (响应某个URI的实现)的实现都是基于类的,不是非常方便,而且3.0之前的版本号还必须通过web.xml配置来添加新的action. servlet中有一个filter的功能,能够配置全部URI的功能都经过filter.我们能够基于filter的功能来实现一个简单的web框架.在这个框架中,主要改进URI action的映射,就像play framework中route的配置: GET /hello c