zoukankan      html  css  js  c++  java
  • tornado

    tornado

    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):
    d={"name":"yuan","l":[123,345,666],"info":{"name":"egon","age":"123"}}
    self.render("templates/index.html",**d)

    def post(self, *args, **kwargs):
    pass

    class LoginHandler(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")
    if user=="alex" and pwd=="123":
    self.redirect("/index")
    print("123ok")
    else:
    self.render("templates/login.html")

    # 路由分配
    application = tornado.web.Application([
    (r"/index", MainHandler),
    (r"/login", LoginHandler),
    ])

    if __name__ == "__main__":
    # 创建socket对象,bind listen
    application.listen(8888)
    # conn,addr=sock.accept()
    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>tornado</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()
  • 相关阅读:
    Windows server 2016 解决“无法完成域加入,原因是试图加入的域的SID与本计算机的SID相同。”
    Windows Server 2016 辅助域控制器搭建
    Windows Server 2016 主域控制器搭建
    Net Framework 4.7.2 覆盖 Net Framework 4.5 解决办法
    SQL SERVER 2012更改默认的端口号为1772
    Windows下彻底卸载删除SQL Serever2012
    在Windows Server2016中安装SQL Server2016
    SQL Server 创建索引
    C#控制台或应用程序中两个多个Main()方法的设置
    Icon cache rebuilding with Delphi(Delphi 清除Windows 图标缓存源代码)
  • 原文地址:https://www.cnblogs.com/zcfx/p/11326380.html
Copyright © 2011-2022 走看看