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 应用并把它转换为 一个响应对象。
原文地址:https://www.cnblogs.com/huaspsw/p/14297812.html