• Tronado


    Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本。这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过为了能有效利用非阻塞式服务器环境,这个 Web 框架还包含了一些相关的有用工具 和优化。

    Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。得利于其 非阻塞的方式和对 epoll 的运用,Tornado 每秒可以处理数以千计的连接,这意味着对于实时 Web 服务来说,Tornado 是一个理想的 Web 框架。我们开发这个 Web 服务器的主要目的就是为了处理 FriendFeed 的实时功能 ——在 FriendFeed 的应用里每一个活动用户都会保持着一个服务器连接。

    pip install tornado
    源码安装
        https://pypi.python.org/packages/source/t/tornado/tornado-4.3.tar.gz

    一、快速上手

    import tornado.ioloop
    import tornado.web
      
      
    class MainHandler(tornado.web.RequestHandler):
        def get(self):
            self.write("Hello, world")
      
    application = tornado.web.Application([
        (r"/index", MainHandler),
    ])
      
      
    if __name__ == "__main__":
        application.listen(8888)
        tornado.ioloop.IOLoop.instance().start()

    第一步:执行脚本,监听 8888 端口

    第二步:浏览器客户端访问 /index  -->  http://127.0.0.1:8888/index

    第三步:服务器接受请求,并交由对应的类处理该请求

    第四步:类接受到请求之后,根据请求方式(post / get / delete ...)的不同调用并执行相应的方法

    第五步:方法返回值的字符串内容发送浏览器

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 #!/usr/bin/env python
     4 # -*- coding:utf-8 -*-
     5 
     6 import tornado.ioloop
     7 import tornado.web
     8 from tornado import httpclient
     9 from tornado.web import asynchronous
    10 from tornado import gen
    11 
    12 import uimodules as md
    13 import uimethods as mt
    14 
    15 class MainHandler(tornado.web.RequestHandler):
    16         @asynchronous
    17         @gen.coroutine
    18         def get(self):
    19             print 'start get '
    20             http = httpclient.AsyncHTTPClient()
    21             http.fetch("http://127.0.0.1:8008/post/", self.callback)
    22             self.write('end')
    23 
    24         def callback(self, response):
    25             print response.body
    26 
    27 settings = {
    28     'template_path': 'template',
    29     'static_path': 'static',
    30     'static_url_prefix': '/static/',
    31     'ui_methods': mt,
    32     'ui_modules': md,
    33 }
    34 
    35 application = tornado.web.Application([
    36     (r"/index", MainHandler),
    37 ], **settings)
    38 
    39 
    40 if __name__ == "__main__":
    41     application.listen(8009)
    42     tornado.ioloop.IOLoop.instance().start()
    异步非阻塞实例

    二、路由系统

    路由系统其实就是 url 和 类 的对应关系,这里不同于其他框架,其他很多框架均是 url 对应 函数,Tornado中每个url对应的是一个类。

    import tornado.ioloop
    import tornado.web
      
      
    class MainHandler(tornado.web.RequestHandler):
        def get(self):
            self.write("Hello, world")
      
    class StoryHandler(tornado.web.RequestHandler):
        def get(self, story_id):
            self.write("You requested the story " + story_id)
      
    class BuyHandler(tornado.web.RequestHandler):
        def get(self):
            self.write("buy.wupeiqi.com/index")
      
    application = tornado.web.Application([
        (r"/index", MainHandler),
        (r"/story/([0-9]+)", StoryHandler),
    ])
      
    application.add_handlers('buy.wupeiqi.com$', [
        (r'/index',BuyHandler),
    ])
      
    if __name__ == "__main__":
        application.listen(80)
        tornado.ioloop.IOLoop.instance().start()

    三、模板

    Tornao中的模板语言和django中类似,模板引擎将模板文件载入内存,然后将数据嵌入其中,最终获取到一个完整的字符串,再将字符串返回给请求者。

    Tornado 的模板支持“控制语句”和“表达语句”,控制语句是使用 {% 和 %} 包起来的 例如 {% if len(items) > 2 %}。表达语句是使用 {{ 和 }} 包起来的,例如 {{ items[0] }}

    控制语句和对应的 Python 语句的格式基本完全相同。我们支持 ifforwhile 和 try,这些语句逻辑结束的位置需要用 {% end %} 做标记。还通过 extends 和 block 语句实现了模板继承。这些在 template 模块 的代码文档中有着详细的描述

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
     5     <title>老男孩</title>
     6     <link href="{{static_url("css/common.css")}}" rel="stylesheet" />
     7     {% block CSS %}{% end %}
     8 </head>
     9 <body>
    10 
    11     <div class="pg-header">
    12 
    13     </div>
    14     
    15     {% block RenderBody %}{% end %}
    16    
    17     <script src="{{static_url("js/jquery-1.8.2.min.js")}}"></script>
    18     
    19     {% block JavaScript %}{% end %}
    20 </body>
    21 </html>
    layout
     1 {% extends 'layout.html'%}
     2 {% block CSS %}
     3     <link href="{{static_url("css/index.css")}}" rel="stylesheet" />
     4 {% end %}
     5 
     6 {% block RenderBody %}
     7     <h1>Index</h1>
     8 
     9     <ul>
    10     {%  for item in li %}
    11         <li>{{item}}</li>
    12     {% end %}
    13     </ul>
    14 
    15 {% end %}
    16 
    17 {% block JavaScript %}
    18     
    19 {% end %}
    index
    import tornado.ioloop
    import tornado.web
      
      
    class MainHandler(tornado.web.RequestHandler):
        def get(self):
            self.render('home/index.html')
      
    settings = {
        'template_path': 'template',
    }
      
    application = tornado.web.Application([
        (r"/index", MainHandler),
    ], **settings)
      
      
    if __name__ == "__main__":
        application.listen(80)
        tornado.ioloop.IOLoop.instance().start()

    四、使用

    import tornado.ioloop
    import tornado.web
    
    #视图
    class MainHandle(tornado.web.RequestHandler):
        def initialize(self):
            print('123')  #在每一次请求开始先执行一下初始化这个方法
        def get(self):
            print(self.get_cookie('user'))
            self.write('hello world')  #默认有个return none
        def post(self,*args,**kwargs):
            pass
    
    class LoginHandle(tornado.web.RequestHandler):
        def get(self,*args,**kwargs):
            self.render('templates/login.html')  #没有脱离文件路径的知识
        def post(self,*args,**kwargs):
            user = self.get_argument('user')
            pwd = self.get_argument('pwd')
            print(user,pwd)
            if user=='haiyan' and pwd=='123':
                self.set_cookie('user','haiyan',10) #设置cookie,10秒后过期
                self.set_secure_cookie('user','haiyan',) #签名cookie
                self.redirect('/index')  #要么return一下
            else:                      #要么else分割开,不然会报错
                self.render('templates/login.html')
            # self.get_arguments() #getlist 像是复选框,一下取多个值
    
    class TestHandle(tornado.web.RequestHandler):
        def get(self, *args, **kwargs):
            sss = {'name':"haiyan","info":{'name':'小华','age':18},"li":[11,22,33]}
            self.render('templates/test.html',**sss)
    
    settings={
        'static_path':'static',
        'xsrf_cookies':True,
        'cookie_secret':'1254'
    }
    #路由分配
    application = tornado.web.Application([
        (r'/index',MainHandle),
        (r'/login',LoginHandle),
        (r'/test',TestHandle)
    ],**settings)
    
    if __name__ == '__main__':
        #创建socket对象,bind.listen
        application.listen(8080)
        # conn,addr = sock.accept
    
        tornado.ioloop.IOLoop.instance().start()

    login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width">
        <title>Title</title>
    </head>
    <body>
    <h4>登录页面</h4>
    <form action="" method="post">
    {#    {{ xsrf_form_html() }}#}
        {% raw  xsrf_form_html() %}  原生的
        用户名:<input type="text" name="user">
        密码:<input type="password" name="pwd">
        <input type="submit" value="登录">
    </form>
    </body>
    </html>

    test.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width">
        <title>Title</title>
        <link rel="stylesheet" href="/static/test.css">  <!--用之前需要配置一下-->
    </head>
    <body>
    <h1>{{ name }}</h1>
    <h2>{{ info.get('age') }}</h2>
    <h1>{{ info['name'] }}</h1>
    <h1>{{ li }}</h1>
    <h1>{{ li[0] }}</h1>
    
    ==================循环生成=============
    <ul>
        {% for i in li%}
        <li>{{ i }}</li>
        {% end %}
    </ul>
    
    
    </body>
    </html>

    五、自定义session

    import tornado.ioloop
    import tornado.web
    
    #视图
    from hashlib import sha1
    import os
    import time
    create_session_id = lambda  :sha1(bytes('%s%s'%(os.urandom(16),time.time()),encoding='')).hexdigest()
    class SessionSix(object):
        session_cache = {  #一开是是NOne的      #开辟一个内存空间,保存这个人的状态
            # 'sddfgfhsdsffd':{},
            # "sdfsdgfgd":{}
        }  #
        def __init__(self,handle):
            self.handle = handle
            #先获取session_id的值
            random_str = self.handle.get_cookie('_session_id')
            if not random_str:
                #如果没有随机字符串,说明是第一次登陆
                random_str = create_session_id()
                self.session_cache[random_str] = {}
            else:
                if random_str not in self.session_cache:#判断他的session_id和自己给它的session_id是否相等
                    random_str = create_session_id()
                    self.session_cache[random_str] = {}#你伪造了一个假的,我就认为你是第一次来
            self.random_str = random_str #来表示不同的用户对应的身份
    
    
        def __setitem__(self, key, value):
            self.session_cache[self.random_str][key] = value
            self.handle.set_cookie('_session_id',create_session_id())
    
        def __getitem__(self, item):
            return self.session_cache[self.random_str].get(item)
    
        def __delitem__(self, key):
            pass
    class MainHandle(tornado.web.RequestHandler):
        def initialize(self):
            self.session = SessionSix(self)
        def get(self):
            print(self.session['user'])  #获取session
            # print(self.get_cookie('user'))
            self.write('hello world')  #默认有个return none
        def post(self,*args,**kwargs):
            pass
    
    class LoginHandle(tornado.web.RequestHandler):
        def initialize(self):
            # print('123')  #在每一次请求开始先执行一下初始化这个方法
            self.session = SessionSix(self)
        def get(self,*args,**kwargs):
            self.render('templates/login.html')  #没有脱离文件路径的知识
        def post(self,*args,**kwargs):
            user = self.get_argument('user')
            pwd = self.get_argument('pwd')
            print(user,pwd)
            if user=='haiyan' and pwd=='123':
                self.session['user'] = '666'  #设置自定义的session
                # self.set_cookie('user','haiyan',10) #设置cookie,10秒后过期
                # self.set_secure_cookie('user','haiyan',) #签名cookie
                self.redirect('/index')  #要么return一下
            else:                      #要么else分割开,不然会报错
                self.render('templates/login.html')
            # self.get_arguments() #getlist 像是复选框,一下取多个值
    
    class TestHandle(tornado.web.RequestHandler):
        def get(self, *args, **kwargs):
            sss = {'name':"haiyan","info":{'name':'小华','age':18},"li":[11,22,33]}
            self.render('templates/test.html',**sss)
    
    settings={
        'static_path':'static',
        'xsrf_cookies':True,
        'cookie_secret':'1254'
    }
    #路由分配
    application = tornado.web.Application([
        (r'/index',MainHandle),
        (r'/login',LoginHandle),
        (r'/test',TestHandle)
    ],**settings)
    
    if __name__ == '__main__':
        #创建socket对象,bind.listen
        application.listen(8080)
        # conn,addr = sock.accept
    
        tornado.ioloop.IOLoop.instance().start()
  • 相关阅读:
    Spring Cloud Eureka(七):DiscoveryClient 源码分析
    Spring Cloud Eureka(六):Eureka Client 如何注册到Eureka Server
    Centos 查看CPU个数、核心数等信息
    Spring Cloud Eureka(五):Eureka Server 启动流程分析
    GlusterFS常用命令
    修改内核参数ip_local_reserved_ports避免tomcat端口占用
    TTM模块安装
    查看磁盘raid信息
    Kubernetes中的PodIP、ClusterIP和外部IP
    ubuntu 14.04.5 kern numa bug
  • 原文地址:https://www.cnblogs.com/morgana/p/8526078.html
Copyright © 2020-2023  润新知