• Python Flask Tornado


    Tornado是一个Python的服务器框架,自带socket是一种异步非阻塞式服务器,速度非常快,每秒可以处理数千以上的连接,对于实时Web服务来说是一个非常理想的Web框架。

    Tornado性能强悍,是一个较为原始的框架,诸多内容需要自己去处理。当然,随着项目越来越大,框架能够提供的功能占比越来越小,更多的内容需要团队自己去实现,而大项目往往需要性能的保证,这时候 Tornado 就是比较好的选择。

    主要特点原生异步非阻塞,IO密集型应用和多任务处理上占据绝对性的优势属于专注型框架
    优点:1. 少而精(轻量级框架)
    2. 注重性能优越,速度快
    3. 解决高并发(请求处理是基于回调的非阻塞调用)
    4. 异步非阻塞
    5. websockets 长连接
    6. 内嵌了HTTP服务器
    7. 单线程的异步网络程序,默认启动时根据CPU数量运行多个实例;利用CPU多核的优势
    8. 自定义模块
    缺点:模板和数据库部分有很多第三方的模块可供选择,这样不利于封装为一个功能模块

    Flask是一个微型的Python开发的Web框架,整个框架只有一个文件。号称 Python 代码写得最好的项目之一。Flask 的灵活性很强,可以自由选择自己的数据库交互组件。

    主要特点:小而轻原生组件几乎为0
    优点:1. 简单,Flask的路由以及路由函数由修饰器设定,开发人员不需要借助其他文件匹配;
    2. 配置灵活,有多种方法配置,不同环境的配置也非常方便;

    1. 环境部署简单,Flask运行不需要借助其他任何软件,只需要安装了PythonIDE,在命令行运行即可。只需要在Python中导入相应包即可满足所有需求;
      4. 入门简单,通过官方指南便可以清楚的了解Flask的运行流程;
      5. 低耦合,Flask可以兼容多种数据库、模板。
      缺点:对于大型网站开发,需要设计路由映射的规则,否则导致代码混乱

    一、Tornado框架的基本组成

    tornado功能概览:

      socket:有(异步非阻塞、支持WebScoket

      路由系统:有

      视图函数:有

      静态文件:有

      ORM操作:无

      模板语言:有

      simple_tag:有,uimethod,uimodule

      cokies:有

      session:无

      csrf:

      xss:

      其他:无

    import tornado.httpserver   # 用来解决web服务器的http协议问题,提供了不少属性方法,实现客户端和服务器端的互通, Tornado的非阻塞、单线程的特点在这个模块中体现
    import tornado.ioloop   # 实现非阻塞socket循环
    import tornado.options  # 命令行解析模块
    import tornado.web  # 提供了一个简单的Web框架与异步功能
    from tornado.options import define, options
    define("port", default=8000, help="run on the given port", type=int)
    class IndexHandler(tornado.web.RequestHandler): # 定义 “请求-处理程序“ 类, tornado.web.RequestHandler 是专门用于完成请求处理程序的
        def get(self):
            greeting = self.get_argument('greeting', 'Hello')   # get_argument()是一个方法, 实列化之后的self对应的就是tornado.web.RequestHandler, 当'greeting'为空时,返回'hello', http://localhost:8000/?greeting=Qiwsir,就可以实现对greeting的赋值
            self.write(greeting + ', welcome you')  # 打印
    if __name__ == "__main__":
        tornado.options.parse_command_line()    # 执行tornado的解析命令行
        app = tornado.web.Application(handlers=[(r"/", IndexHandler)])  # 实列化, 在一般情况下,handlers是不能为空的, 因为Application类通过这个参数的值处理所得到的请求
        http_server = tornado.httpserver.HTTPServer(app)    # HTTPServer是一个单线程非阻塞HTTP服务器, 执行HTTPServer一般要回调Application对象,并提供发送响应的接口, 也就是下面的内容是跟随上面语句的
        http_server.listen(options.port)
        tornado.ioloop.IOLoop.instance().start()    # 表示可以接收来自HTTP的请求了
    View Code

    二、Tornado自带功能

    1. Tornado执行流程

     

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

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

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

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

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

     

     

    浏览器访问: http://127.0.0.1:8888/index/ 输出:hellow ,world

    浏览器访问: http://127.0.0.1:8888/login/ 输出:hellow ,world, hello, hello, psw

    1. 路由系统

    2.1 动态路由

    动态URL传参:

     

    浏览器访问:http://127.0.0.1:8888/login/123  输出:hellow ,world123

    tornado中传递参数的几种方式

    方法一 tornado路由可以使用正则表达式中的子表达式传递url参数。例如:(r"/login/(d+)",Login) 匹配以后,tornado会将字符串()中匹配到的内容,作为参数传递到Login中去,因此我们在Login中定义get方法时增加参数

     

    方法二 :通过 self.get_argument()

    tornadogetpost提交的参数都可以通过self.get_argument()获得,只需要填写第一个参数值即可一次性获取所有的参数方法:self.get_arguments()

    方法三 self.request.body

    tornado的参数存储在self.request.body内,通过JSON以后就可以直接取值。

    2.2 域名匹配

    可以进行域名绑定,因为是一串正则,所以支持多域名。

     

    2.3 反向生成url

     

    1. 视图

    tornado的视图才有CBV模式,URL匹配成功之后,视图执行顺序为 initialize prepareget/post/put/deletefinish

     

    3.1 请求相关

    self.get_body_argument('user') :获取POST请求携带的参数

    self.get_body_arguments('user_list') :获取POST请求参数列表(如chebox标签和select多选)

    self.request.body.decode('utf-8'):获取json数据

    self.get_query_argument('user') :获取GET请求携带的参数

    self.get_query_arguments('user_list') :获取GET请求参数列表(如chebox标签和select多选)

    self.get_argument('user') :获取GETPOST请求携带的参数

    self.get_arguments('user_list'):获取GETPOST请求参数列表(如chebox标签和select多选)

    注:以上取值方式如果取不到值就会报错,可以设置取不到值就取None;(例如 self.get_argument('user'None)

    3.2 响应相关

    self.write()  响应字符串

    self.render() 响应页面

    self.redirect(): 页面跳转

    1. 引入静态文件

     

    通过static_url()方法引入静态文件的好处: 

    1、使用static_url()可以不用考虑静态文件修改之后造成引用失效的情况;

    2、还会生成静态文件url会有一个v=...的参数,这是tornado根据静态文件MD5之后的值,如果后台的静态文件修改,这个值就会变化,前端就会重新向后台请求静态文件,保证页面实时更新,不引用浏览器缓存。

    上下文对象:

    如果模板语言中声明了变量,上下文对象必须对应传值,如果没有就设置为空,否则会报错;

    1. Cokies

    5.1 设置Cokies

     

    获取cokies:self.get_cookie('username')

    设置在用户不断刷新页面的情况,cookies不过期;

     

    5.2 Tornado加密cokie

    配置加密规则使用的字符串

     

    设置加密的cokies:self.set_secure_cookie('username',user,expires=v)

    获取加密的cokies:self.get_secure_cookie('username')

    设置在用户不断刷新页面的情况,SecureCookies不过期;

     

    5.3 @authenticated 装饰器

    执行 self.curent_user,有值就登录用户,无就去执行get_curent_user方法,get_curent_user没有返回用户信息,会记录当前url更加配置文件跳转到登录页面;

     

     

    Tornado使用表单和模板:tornado模板self.render和模板变量传递:

     

     

     

    Tornado可以运用future对象,进行异步处理:

    tornado解决异步请求就是利用future对象。future对象中设定默认参数result=None,如果在某一时刻future的result中被设定值了,那么它就会自动执行回调函数,实际上这种执行回调函数的功能就是所谓的异步,不需要服务器等待,自己自动执行完后会进行回调。

    一个最小的Flask应用如下:

    from flask import Flask
    
    app = Flask(__name__)
    
    @app.route('/')def hello_world():
    
        return 'Hello, World!'
    View Code

      

    1. 首先我们导入了 Flask 类。 该类的实例将会成为我们的 WSGI 应用。
    2. 接着我们创建一个该类的实例。第一个参数是应用模块或者包的名称。如果你使用 一个单一模块(就像本例),那么应当使用 __name__ ,因为名称会根据这个 模块是按应用方式使用还是作为一个模块导入而发生变化(可能是 ‘__main__’ , 也可能是实际导入的名称)。这个参数是必需的,这样 Flask 才能知道在哪里可以 找到模板和静态文件等东西。更多内容详见 Flask 文档。
    3. 然后我们使用 route() 装饰器来告诉 Flask 触发函数的 URL 。
    4. 函数名称被用于生成相关联的 URL 。函数最后返回需要在用户浏览器中显示的信息。

    1、路由

    使用route()装饰器来把函数绑定到URL:

    1 @app.route('/post/<int:post_id>')
    2 
    3 def show_post(post_id):
    4 
    5 return 'Post %d' % post_id
    View Code
    1. /…/里面的内容是URL的路径名,<…>里面的内容是接收的参数,默认为string类型。
    2. 转换器类型:

     

    2、HTTP

    Web应用使用不同的HTTP方法处理URL。当你使用Flask时,应当熟悉 HTTP方法。缺省情况下,一个路由只回应GET请求。可以使用route()装饰器的methods参数来处理不同的HTTP方法:

     1 from flask import request
     2 
     3 @app.route('/login', methods=['GET', 'POST'])
     4 
     5 def login():
     6 
     7     if request.method == 'POST':
     8 
     9         return do_the_login()
    10 
    11     else:
    12 
    13         return show_the_login_form()
    View Code

    3、渲染模板

    使用render_template('模板名','变量')方法可以渲染模板,只需要提供模板名称和需要作为参数传递给模板的变量就可以了

    from flask import render_template
    
    @app.route('/hello/<name>')
    
    def hello(name=None):
    
        return render_template('hello.html', name=name)
    View Code

    4、请求对象

    request通过使用method属性可以操作当前请求方法,通过使用form属性处理表单数据。

    5、文件上传

    在HTML表单中设置enctype="multipart/form-data" 属性。已上传的文件被储存在内存或文件系统的临时位置。你可以通过请求对象files属性来访问上传的文件。每个上传的文件都储存在这个 字典型属性中。这个属性基本和标准 Python file对象一样,另外多出一个 用于把上传文件保存到服务器的文件系统中的save()方法。

    from flask import request
    
    @app.route('/upload', methods=['GET', 'POST'])
    
    def upload_file():
    
        if request.method == 'POST':
    
            f = request.files['the_file']
    
            f.save('/var/www/uploads/uploaded_file.txt')
    View Code

    如果想要知道文件上传之前其在客户端系统中的名称,可以使用filename属性。但是请牢记这个值是可以伪造的,永远不要信任这个值。如果想要把客户端的文件名作为服务器上的文件名,可以通过Werkzeu提供的secure_filename() 函数:

    from flask import request
    
    from werkzeug.utils import secure_filename
    
    @app.route('/upload', methods=['GET', 'POST'])
    
    def upload_file():
    
        if request.method == 'POST':
    
            f = request.files['the_file']
    
            f.save('/var/www/uploads/' + secure_filename(f.filename))
    View Code

    6、Cookies

    要访问cookies,可以使用cookies属性。可以使用响应对象的set_cookie方法来设置cookies。请求对象的cookies属性是一个包含了客户端传输的所有cookies的字典。

    读取cookies:

    from flask import request
    
    @app.route('/')
    
    def index():
    
        username = request.cookies.get('username')
    View Code

    储存cookies:

    from flask import make_response
    
    @app.route('/')
    
    def index():
    
        resp = make_response(render_template(...))
    
        resp.set_cookie('username', 'the username')
    
        return resp
    View Code

    7、重定向和错误

    使用redirect()函数可以重定向。使用abort()可以更早退出请求,并返回错误代码:

    from flask import abort, redirect, url_for
    
    @app.route('/')
    
    def index():
    
        return redirect(url_for('login'))
    
    @app.route('/login')
    
    def login():
    
        abort(401)
    
        this_is_never_executed()
    View Code

    上例实际上是没有意义的,它让一个用户从索引页重定向到一个无法访问的页面(401表示禁止访问)。但是上例可以说明重定向和出错跳出是如何工作的。缺省情况下每种出错代码都会对应显示一个黑白的出错页面。使用 errorhandler()装饰器可以定制出错页面:

    from flask import render_template
    
    @app.errorhandler(404)
    
    def page_not_found(error):
    
        return render_template('page_not_found.html'), 404
    View Code

    8、响应

    1. 如果视图返回的是一个响应对象,那么就直接返回它。
    2. 如果返回的是一个字符串,那么根据这个字符串和缺省参数生成一个用于返回的响应对象。
    3. 如果返回的是一个字典,那么调用 jsonify 创建一个响应对象。
    4. 如果返回的是一个元组,那么元组中的项目可以提供额外的信息。元组中必须至少 包含一个项目,且项目应当由 (response, status) 、 (response, headers) 或者 (response, status, headers) 组成。 status 的值会重载状态代码, headers 是一个由额外头部值组成的列表 或字典。
    5. 如果以上都不是,那么 Flask 会假定返回值是一个有效的 WSGI 应用并把它转换为 一个响应对象。
  • 相关阅读:
    wc项目
    随笔之——伪类选择器:nthchild(n) 与 nthoftype(n)的区别!!!
    随笔之——浮动(float)的影响及其清除、、clear与overflowhidden清除float的不同!!!
    随笔之——各大热门网站search 搜索框的写法,浅析!
    一个简单的注册页面
    自我介绍、目标
    position的6个属性的实验和相关分析
    第二次作业
    第三次作业
    第一次作业
  • 原文地址:https://www.cnblogs.com/huaspsw/p/14297812.html
Copyright © 2020-2023  润新知