用python写一个简单的web框架
admin
2023-07-30 21:03:31
0

最近在实验室也没什么事情做,闲着无聊。于是想着造轮子,最后决定写一个简单的web框架玩玩。

STEP.1


我们首先得选择基于什么协议来写这种框架。我们可以选择CGI协议,或者是WSGI接口。如果使用CGI,实际上我们只是按着CGI的规范写了一个python程序,然后每次服务器收到请求,就fork一个程序来执行它,然后返回一个http文档,性能比较低下。对于WSGI,而是一个存在于服务器和应用间的接口,在WSGI之前,web应用都是依赖于服务器的,现在流行的python框架都支持WSGI接口。

STEP.2 PEP-333


这一段是PEP-333 所提供的样例代码。

def simple_app(environ, start_response):
    \"\"\"Simplest possible application object\"\"\"
    status = \'200 OK\'
    response_headers = [(\'Content-type\', \'text/plain\')]
    start_response(status, response_headers)
    return [\'Hello world!\\n\']

这里的application被传入了两个值。

  • environ
  • start_response。
    environ是一个字典,保存了http请求的信息。
    start_response是一个函数,发送http响应。她有两个参数status 和 start_headers。
  • status必须是由状态编号和具体信息组成的字符串,必须符合RFC 2616。
  • start_headers是一个(header_name,header_value) 元组的列表元组列表。其中的hearder_name必须是合法的http header字段名。在RFC 2616, Section 4.2中有详细定义。
    当然官方还给出了类的实现。

    def __init__(self, environ, start_response):
    
          self.environ = environ
    
          self.start = start_response
      def __iter__(self):
    
          status = \'200 OK\'
    
          response_headers = [(\'Content-type\',\'text/plain\')]
    
          self.start(status, response_headers)
    
          yield \"Hello world!\\n\"

    了解了如上信息后,基本上可以开始了。我们就到官方给的代码上进行修改吧。

STEP.3 将路径链接到函数


首先我们得把用户请求的路径,链接到函数。我们可以实现一个getPage方法,专门做这件事。我们所拥有的信息,只有environ[\’PATH_INFO\’]。

urls = [(\'^/index/$\',\'func_index\'),
        (\'^/comment/$\',\'func_comment\'),
        (\'^/environ/$\',\'get_environ\'),
        (\'^/post/$\',\'post_test\')]#urls是提供给app开发者来做链接的。
    def getPage(self):
        path = self.environ[\'PATH_INFO\']
        for pattern in self.urls:
            m = re.match(pattern[0],path)#将urls元素的第0项和path进行比对,如果匹配上了,返回函数名
            if m:
                function = getattr(self,pattern[1])#getattr方法来得到函数
                return function()
        return \'404 not found\'#没匹配上任何东西

写到这里之后,每次添加页面,就只需要在urls列表中添加一个元祖就行了。

STEP.4 获取模版


既然是写web app,模版肯定是得有的。这里我提供了一种getTemplate方法来做这件事。不过我只提供了变量的替换。

    def getTemplate(self,tem_name,rep=0):
        #这个函数返回内容,tem_name是文件名字
        #参数rep是一个字典,默认为0
        f = open(\'template/\'+tem_name)
        html = f.read()
        if(rep!=0):
            for to_replace in rep:
                strinfo = re.compile(\'\\{\\%\\s*\'+str(to_replace)+\'\\s*\\%\\}\')
                html = strinfo.sub(rep[to_replace],html)
        return html

STEP.5 POST数据的处理


要想获取POST数据,我们得通过environ[\’wsgi.input\’]来处理。而他实际上就是系统的标准输入。

 environ[\'wsgi.input\']        = sys.stdin

知道这点后就很好写了。

    def getPost(self):
        if(self.environ[\'REQUEST_METHOD\'] == \'POST\'):
            try:
                request_body_size = int(self.environ.get(\'CONTENT_LENGTH\', 0))#读出content_length的值
            except:
                request_body_size = 0
            request_body = self.environ[\'wsgi.input\'].read(request_body_size) #请求的body
            post_data = parse_qs(request_body)#parse_qs是cgi提供的方法,帮助我们处理请求
            return post_data

数据库的链接


import MySQLdb
class Model(object):
    def __init__(self):
            self.host = \'localhost\'
            self.port = 3306
            self.user = \'admin\'
            self.passwd = \'admin\'
            self.db = \'xieyi\'
    def build_connect(self):
        self.conn = MySQLdb.connect(
            host = self.host,
            port = self.port,
            user = self.user,
            passwd = self.passwd,
            db = self.db
            )
    def exec_ins(self,ins):
        cur = self.conn.cursor()
        num = cur.execute(ins)
        info = {} 
        if(num>0):
            info = cur.fetchmany(num)
        cur.close()
        self.conn.commit()
        return info 
    def close(self):
        self.conn.close()

STEP.6 清理工作


很多配置如果放到代码中,会增加阅读负担。于是把urls,model抽取出来。
使得配置更加方便。

STEP.7 结束


这只是一个web框架简易的实现,仅供娱乐。如有疏漏,还望指出。
代码po在https://github.com/bloodycoder/skeleton

上一篇:Hack On Douyu — 1

下一篇:Django学习笔记

相关内容

热门资讯

500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
python绘图库Matplo... 本文简单介绍了Python绘图库Matplotlib的安装,简介如下: matplotlib是pyt...
Prometheus+Graf... 一,Prometheus概述 1,什么是Prometheus?Prometheus是最初在Sound...