zoukankan      html  css  js  c++  java
  • Python学习

    自己动手写一个web框架,因为我是菜鸟,对于python的一些内建函数不是清楚,所以在写这篇文章之前需要一些python和WSGI的预备知识,这是一系列文章。这一篇只实现了如何处理url。

    参考这篇文章:http://www.cnblogs.com/russellluo/p/3338616.html

    预备知识

    web框架主要是实现web服务器和web应用之间的交互。底层的网络协议主要有web服务器完成。譬如监听端口,填充报文等等。

    Python内建函数__iter__和__call__和WSGI

    迭代器iterator

    迭代器为类序列对象提供了类序列的接口,也就是说类序列对象可以通过迭代器像序列一样进行迭代。说简单一点就是遍历对象。如果想让类是可迭代的,那么就必须实现__iter__和next()。

    __call__

    只要在类定义的时候实现了__call__方法,那么该类的对象就是可调有的,即可以将对象当做函数来使用。这里只用明白什么是__call__函数即可,因为WSGI规范中用要求。

    WSGI

    关于WSGI的介绍可以点击http://webpython.codepoint.net,有很详细的介绍。这里只说明一下大概。WSGI接口是用可调用的对象实现的:一个函数,一个方法或者一个可调用的实例。下面是一个实例,注释写的很详细:

    # This is our application object. It could have any name,
    # except when using mod_wsgi where it must be "application"
    def application( # It accepts two arguments:
          # environ points to a dictionary containing CGI like environment variables
          # which is filled by the server for each received request from the client
          environ,
          # start_response is a callback function supplied by the server
          # which will be used to send the HTTP status and headers to the server
          start_response):
    
       # build the response body possibly using the environ dictionary
       response_body = 'The request method was %s' % environ['REQUEST_METHOD']
    
       # HTTP response code and message
       status = '200 OK'
    
       # These are HTTP headers expected by the client.
       # They must be wrapped as a list of tupled pairs:
       # [(Header name, Header value)].
       response_headers = [('Content-Type', 'text/plain'),
                           ('Content-Length', str(len(response_body)))]
    
       # Send them to the server using the supplied function
       start_response(status, response_headers)
    
       # Return the response body.
       # Notice it is wrapped in a list although it could be any iterable.
       return [response_body]
    

     简单来说就是根据接收的参数来返回相应的结果。

    设计web框架

    我之前用过django写过一个很简单的博客,目前放在SAE上,好久没更新了。网址:http://3.mrzysv5.sinaapp.com。一个web框架最基本的要求就是简化用户的代码量。所以在django中,我只需要写view、model和url配置文件。下面是我用django时写的一个处理视图的函数:

    def blog_list(request):
        blogs = Article.objects.all().order_by('-publish_date')
        blog_num = Article.objects.count()
        return render_to_response('index.html', {"blogs": blogs,"blog_num":blog_num}, context_instance=RequestContext(request))
    def blog_detail(request):
        bid = request.GET.get('id','')
        blog = Article.objects.get(id=bid)
        return render_to_response('blog.html',{'blog':blog})
    

     需要我完成的就是操作数据库,返回相应的资源。所以我要编写的web框架就要尽可能的封装一些底层操作,留给用户一些可用的接口。根据我的观察,web框架的处理过程大致如下:

    1. 一个WSGI应用的基类初始化时传入配置好的url文件
    2. 用户写好处理方法,基类根据url调用方法
    3. 返回给客户端视图

    一个WSGI基类,主要有以下的功能:

    • 处理environ参数
    • 根据url得到方法或者类名,并执行后返回
    import re
    class WSGIapp:
    
        headers = []
    
        def __init__(self,urls=()):
            self.urls = urls
            self.status = '200 OK'
    
        def __call__(self,environ,start_response):
    
            x = self.mapping_urls(environ)
            print x
            start_response(self.status,self.headers)
    
            if isinstance(x,str):
                return iter([x])
            else:
                return iter(x)
    
        def mapping_urls(self,environ):
            path = environ['PATH_INFO']
    
            for pattern,name in self.urls:
                m = re.match('^'+pattern+'$',path)
                if m:
                    args = m.groups()
                    func = globals()[name]
                    return func(*args)
            return self.notfound()
    
        def notfound(self):
            self.status = '404 Not Found'
            self.headers = [('Content-Type','text/plain')]
            return '404 Not Found
    '
    
        @classmethod
        def header(cls,name,value):
            cls.headers.append((name,value))
    
    def GET_index(*args):
        WSGIapp.header('Content-Type','text/plain')
        return 'Welcome!
    '
    def GET_hello(*args):
        WSGIapp.header('Content-Type','text/plain')
        return 'Hello %s!
    ' % args
    urls = [
        ('/','GET_index'),
        ('/hello/(.*)','GET_hello')
        ]
    wsgiapp = WSGIapp(urls)
    
    if __name__ == '__main__':
        from wsgiref.simple_server import make_server
        httpd = make_server('',8000,wsgiapp)
        print 'server starting...'
        httpd.serve_forever()
    

     上面的代码是不是很简介了,只需要定义函数即可。

  • 相关阅读:
    小程序组件事件
    关于微信小程序中组件和页面对全局样式的继承性
    创建Java程序并设置快捷提示
    微信小程序设置全局字体
    微信小程序组件的使用
    微信开发者工具的一些快捷键
    消除flex-wrap之后每个item上下的距离
    flex布局中的主轴和侧轴的确定
    C++string中用于查找的find系列函数浅析
    C++11 图说VS2013下的引用叠加规则和模板参数类型推导规则
  • 原文地址:https://www.cnblogs.com/mr-zys/p/4106990.html
Copyright © 2011-2022 走看看