iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Tornado基础学习篇
  • 811
分享到

Tornado基础学习篇

基础Tornado 2023-01-30 22:01:06 811人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

1.1 Tornado是什么? Tornado是使用python编写的一个强大的、可扩展的WEB服务器。它在处理严峻的网络流量时表现得足够强健,但却在创建和编写时有着足够的轻量级,并能够被用在大量的应用和工具中。 我们现在所知道的Tor

1.1 Tornado是什么?

Tornado是使用python编写的一个强大的、可扩展的WEB服务器。它在处理严峻的网络流量时表现得足够强健,但却在创建和编写时有着足够的轻量级,并能够被用在大量的应用和工具中。

我们现在所知道的Tornado是基于Bret Taylor和其他人员为FriendFeed所开发的网络服务框架,当FriendFeed被Facebook收购后得以开源。不同于那些最多只能达到10,000个并发连接的传统网络服务器,Tornado在设计之初就考虑到了性能因素,旨在解决C10K问题,这样的设计使得其成为一个拥有非常高性能的框架。此外,它还拥有处理安全性、用户验证、社交网络以及与外部服务(如数据库和网站api)进行异步交互的工具。

延伸阅读:C10K问题

基于线程的服务器,如Apache,为了传入的连接,维护了一个操作系统线程池。Apache会为每个Http连接分配线程池中的一个线程,如果所有的线程都处于被占用的状态并且尚有内存可用时,则生成一个新的线程。尽管不同的操作系统会有不同的设置,大多数linux发布版中都是默认线程堆大小为8MB。Apache的架构在大负载下变得不可预测,为每个打开的连接维护一个大的线程池等待数据极易迅速耗光服务器的内存资源。

大多数社交网络应用都会展示实时更新来提醒新消息、状态变化以及用户通知,这就要求客户端需要保持一个打开的连接来等待服务器端的任何响应。这些长连接或推送请求使得Apache的最大线程池迅速饱和。一旦线程池的资源耗尽,服务器将不能再响应新的请求。

异步服务器在这一场景中的应用相对较新,但他们正是被设计用来减轻基于线程的服务器的限制的。当负载增加时,诸如node.js,lighttpd和Tornodo这样的服务器使用协作的多任务的方式进行优雅的扩展。也就是说,如果当前请求正在等待来自其他资源的数据(比如数据库查询或HTTP请求)时,一个异步服务器可以明确地控制以挂起请求。异步服务器用来恢复暂停的操作的一个常见模式是当合适的数据准备好时调用回调函数。我们将会在第五章讲解回调函数模式以及一系列Tornado异步功能的应用。

自从2009年9月10日发布以来,TornadoTornado已经获得了很多社区的支持,并且在一系列不同的场合得到应用。除FriendFeed和Facebook外,还有很多公司在生产上转向Tornado,包括Quora、Turntable.fm、Bit.ly、Hipmunk以及MyYearbook等。

总之,如果你在寻找你那庞大的CMS或一体化开发框架的替代品,Tornado可能并不是一个好的选择。Tornado并不需要你拥有庞大的模型建立特殊的方式,或以某种确定的形式处理表单,或其他类似的事情。它所做的是让你能够快速简单地编写高速的Web应用。如果你想编写一个可扩展的社交应用、实时分析引擎,或RESTful API,那么简单而强大的Python,以及Tornado正是为你准备的!

 

tornado和其他的框架如Django,flask相比优缺点

DjanGo

优点:

  • 大和全(重量级框架)
  • 自带ORM,template,view 
  • 需要的功能也可以去找第三方的app
  • 注重高效开发
  • 自动化的管理后台(只需要使用起ORM,做简单的定义,就能自动生成数据库结构,全功能的管理后台)
  • session功能

缺点:

  • template不怎么好用(来自自身的缺点)
  • 数据库用NoSQL不方便(来自自身的缺点)
  • 如果功能不多,容易臃肿

 

Tornado

优点:

  • 少而精(轻量级框架)
  • 注重性能优越,速度快
  • 解决高并发(请求处理是基于回调的非阻塞调用)
  • 异步非阻塞
  • websockets 长连接
  • 内嵌了HTTP服务器
  • 单线程的异步网络程序,默认启动时根据CPU数量运行多个实例;利用CPU多核的优势
  • 自定义模块

缺点:

  • 模板和数据库部分有很多第三方的模块可供选择,这样不利于封装为一个功能模块

 

总结

要性能, Tornado 首选;要开发速度,Django 和 Flask 都行,区别是 Flask 把许多功能交给第三方库去完成了,因此 Flask 更为灵活。

 

综上所述:

Django适合初学者或者小团队的快速开发,适合做管理类、博客类网站、或者功能十分复杂需求十分多的网站

Tornado适合高度定制,适合访问量大,异步情况多的网站

 

选择适合的才是最好的

1.2快速入门

这里我就不写安装步骤了,pip3 install tornado

hello,Tornado     从get请求例子开始

import tornado
from tornado import ioloop,httpserver
from tornado.web import RequestHandler,url
from tornado.options import define,options


tornado.options.define("port",type=int,default=8002,help="服务器客户端")   #默认配置
class IndexHandler(RequestHandler):
    def get(self):#get请求
        self.write("hello Tornado")  #发送hello Tornado到缓冲区,可以发送多个,这里到最后会默认执行self.finish(),将所有缓冲区信息发送给报文
#入口文件
if __name__ == '__main__':
    tornado.options.parse_command_line()
    app = tornado.web.Application([(r"/",IndexHandler),],
                                  debug=True)   #路由映射
    http_server  = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)      #监听8002端口
    tornado.ioloop.IOLoop.current().start()  #开始循环监听

通过上面代码我们了解了tornado运行过程

tornado的基础web框架模块

RequestHandler
封装了对应一个请求的所有信息和方法,write(响应信息)就是写响应信息的一个方法;对应每一种http请求方式(get、post等),把对应的处理逻辑写进同名的成员方法中(如对应get请求方式,就将对应的处理逻辑写在get()方法中),当没有对应请求方式的成员方法时,会返回“405: Method Not Allowed”错误。

Application
Tornado Web框架的核心应用类,是与服务器对接的接口,里面保存了路由信息表,其初始化接收的第一个参数就是一个路由信息映射元组的列表;其listen(端口)方法用来创建一个http服务器实例,并绑定到给定端口(注意:此时服务器并未开启监听)

Tornado核心IOLoop循环模块

tornado的核心io循环模块,封装了Linux的epoll和BSD的kqueue,tornado高性能的基石。 以Linux的epoll为例,其原理如下图:

IOLoop.current() 返回当前线程的IOLoop实例。

IOLoop.start() 启动IOLoop实例的I/O循环,同时服务器监听被打开。

小结:

  1. tornado高性能Web原理是利用Linux epoll IO多路模型和协程异步编程

  2. tornado Web框架核心模块是 web 和 核心事件循环模块是 IOLoop

1.3基础应用

上面的例子是get请求,下面我们再来看一下post请求如何做

Post请求

import tornado
from tornado import ioloop,httpserver
from tornado.web import RequestHandler,url
from tornado.options import define,options


tornado.options.define("port",type=int,default=8002,help="服务器客户端")
class IndexHandler(RequestHandler):
    def post(self):
        # a = self.get_body_arguments("a") 
        a = self.get_body_argument("a")
        print(a)
        self.write("a的值为%s"%a)
#入口文件
if __name__ == '__main__':
    tornado.options.parse_command_line()
    app = tornado.web.Application([(r"/",IndexHandler),],
                                  debug=True)
    http_server  = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.current().start()

使用RequestHandler对象的get_argument方法来捕获请求查询字符串的的参数。

get_argument可以获取post请求和get请求的全部参数。

get_query_argument获取get请求的所有参数。

get_body_argument获取get请求的所有参数。

这里需要注意的是上面的三个方法如果遇到相同的查询字符串,会以最后查询到的字符串值为结果。

这里返回的是最后一个a的值,大家可能会有一问,如果我想获取所有a的值,改怎么做呢。

很简单,上面代码中有个方法我给注释了,没错,就是get_body_arguments,方法会返回所有的a的结果数组

 

 

 

Post发送JSON请求

在tornado中post请求接收的参数只允许使用两种格式

但是如果想发送json请求,我们就需要自定义解析json文件的过程

# coding:utf-8
import tornado
from tornado import ioloop,httpserver
from tornado.web import RequestHandler,url
from tornado.options import define,options
import json,time
tornado.options.define("port",type=int,default=8002,help="服务器客户端")
class IndexHandler(RequestHandler):

    def post(self):
        #json请求 解析
        if self.request.headers.get("Content-Type").startswith("application/json"): #判断请求格式
            json_data = self.request.body            #获取请求json
            json_data = str(json_data,'utf-8')       #转换字符串
            json_args = json.loads(json_data)          #转换字典
            self.write(json_args)

#入口文件
if __name__ == '__main__':
    tornado.options.parse_command_line()
    app = tornado.web.Application([(r"/",IndexHandler),
                                   ],
                                  debug=True)
    http_server  = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.current().start()

request.headers.get方法用来获取报头信息,request.body获取body。

结果:

 

 Post请求上传文件

import tornado
from tornado import ioloop, httpserver
from tornado.web import RequestHandler, url
from tornado.options import define, options
import json, time

tornado.options.define("port", type=int, default=8002, help="服务器客户端")


class IndexHandler(RequestHandler):

    def post(self):
        # 上传文件
        image1 = self.request.files["image1"][0]["body"]
        with open("image1.jpg",'wb')as f:  #文件保存
            f.write(image1)
            f.close()
        self.write("上传成功")



# 入口文件
if __name__ == '__main__':
    tornado.options.parse_command_line()
    app = tornado.web.Application([(r"/", IndexHandler)

                                   ],
                                  debug=True)
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.current().start()

request.files方法可以接受上传文件,我们需要做的就是保存文件操作。

使用表单格式可以上传文件如图:

 

 

set_header方法自定义请求头

import tornado
from tornado import ioloop, httpserver
from tornado.web import RequestHandler, url
from tornado.options import define, options
import json, time

tornado.options.define("port", type=int, default=8002, help="服务器客户端")


class IndexHandler(RequestHandler):
    # 自定义header
    def set_default_headers(self):
        self.set_header("Content", "application/json; charset=UTF-8")
        self.set_header("itcast", "python")

    def get(self):

        # 返回json数据
        stu = {
            "name": 'zhaozhi',
            "age": 24,
            'sex': "男"
        }
        self.write(stu)


# 入口文件
if __name__ == '__main__':
    tornado.options.parse_command_line()
    app = tornado.web.Application([(r"/", IndexHandler),

                                   ],
                                  debug=True)
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.current().start()

函数set_default_headers函数是RequestHanlder的方法,用于设置全局默认header。

如果在get请求中出现set_header方法并且定义header属性和全局设置有相同,以get请求局部设置的header属性值为优先。

 

Http状态码

可以使用RequestHandler类的set_status()方法自定义设置HTTP状态码。有很多定义好的状态码,例如:

404 Not Found

Tornado会在HTTP请求的路径无法匹配任何RequestHandler类相对应的模式时返回404(Not Found)响应码。

400 Bad Request

如果你调用了一个没有默认值的get_argument函数,并且没有发现给定名称的参数,Tornado将自动返回一个400(Bad Request)响应码。

405 Method Not Allowed

如果传入的请求使用了RequestHandler中没有定义的HTTP方法(比如,一个POST请求,但是处理函数中只有定义了get方法),Tornado将返回一个405(Methos Not Allowed)响应码。

500 Internal Server Error

当程序遇到任何不能让其退出的错误时,Tornado将返回500(Internal Server Error)响应码。你代码中任何没有捕获的异常也会导致500响应码。

200 OK

如果响应成功,并且没有其他返回码被设置,Tornado将默认返回一个200(OK)响应码。

 

set_status()方法有两个参数,第一个为状态码,第二个为响应结果(已有状态码可以不设置此参数,新的状态码必须设置)。这里就不给示例了,可以自己尝试写一下

你想使用自己的方法代替默认的错误响应,你可以重写write_error方法在你的RequestHandler类中。(检测到异常会抛出)

我们也可以在get方法中使用send_error方法来直接抛出异常。这两种方法和set_status方法参数一致。

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web

from tornado.options import define, options
define("port", default=8002, help="run on the given port", type=int)

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        greeting = self.get_argument('greeting', 'Hello')
        self.write(greeting + ', friendly user!')
    def write_error(self, status_code, **kwargs):
        self.write("Gosh darnit, user! You caused a %d error." % status_code)

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(handlers=[(r"/", IndexHandler)])
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

 

redirect方法实现登录跳转

import tornado
from tornado import ioloop, httpserver
from tornado.web import RequestHandler, url
from tornado.options import define, options

tornado.options.define("port", type=int, default=8002, help="服务器客户端")


class IndexHandler(RequestHandler):

    def get(self):
        self.write("登录成功")


#登录模块
class LoginHandler(RequestHandler):
    def get(self):
        self.write("<form method='post'><input type='submit' value='登录'></form>  ")

    def post(self):
        self.redirect('/')


# 入口文件
if __name__ == '__main__':
    tornado.options.parse_command_line()
    app = tornado.web.Application([(r"/", IndexHandler),
                                   (r"/login", LoginHandler),
                                   ],
                                  debug=True)
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.current().start()

不知道有小伙伴注意到了没,关于debug=True,调试模式,为什么修改代码后不会自动重启。

没找到原因(知道原因的小伙伴评论区解释一下),不过找到了另一个方法,import tornado.autoreload,导入模块就可以自动重启了,有兴趣的小伙伴可以取看看源码。这里就不解释了。

 

本文部分参考tornado中文文档 http://demo.pythoner.com/itt2zh/ch1.html

本章节到这里就结束了,谢谢大家阅读,感兴趣的话加个关注,后续还会继续更新。

--结束END--

本文标题: Tornado基础学习篇

本文链接: https://www.lsjlt.com/news/180408.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Tornado基础学习篇
    1.1 Tornado是什么? Tornado是使用Python编写的一个强大的、可扩展的Web服务器。它在处理严峻的网络流量时表现得足够强健,但却在创建和编写时有着足够的轻量级,并能够被用在大量的应用和工具中。 我们现在所知道的Tor...
    99+
    2023-01-30
    基础 Tornado
  • Python学习基础篇(一)
    Python简介和入门Python简介走进Pythonpython的创始人为吉多·范罗苏姆(Guido van Rossum)。1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一...
    99+
    2023-01-31
    基础 Python
  • [Python]学习基础篇:字典
    字典字典这个数据结构的功能和它的名字一样,根据key得到value值。字典的定义 方法: dict={‘key1’:value1,’key2’:value2……..} 对于字典,key值在字典中不能重复,若出现重复,将更改原有的key对应的...
    99+
    2023-01-31
    字典 基础 Python
  • Kotlin基础学习-入门篇
    本篇文章来自郭霖大佬的第一行代码中的Kotlin教程,笔者只是在学习Kotlin过程中记录学习过程。 Kotlin系列已更新: Kotlin基础学习-入门篇 Kotlin基础学习-第二篇 Kotli...
    99+
    2023-09-07
    kotlin android
  • CTF之PHP基础学习篇(一)
    文章目录 前言CTF之PHP基础一、PHP是什么?二、配置PHP环境三、php基础语法 总结 前言 估摸着不少学计算机的同学以及其他专业的小部分同学都对于信息安全感兴趣吧!那对于参加...
    99+
    2023-10-02
    php 网络安全 学习
  • [Python]学习基础篇:常见的Pyt
    函数列表进制转换函数函数名称及参数功能用例bin(x)将数值x转化为二进制>>> x=10 >>> bin(10) 10hex(x)将数值x转化为十六进制>>> x=10 &g...
    99+
    2023-01-31
    常见 基础 Python
  • Netty学习教程之基础使用篇
    什么Netty?Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。也就是说,Netty 是一个基于NIO的客户、服务器端编程框架...
    99+
    2023-05-31
    netty 基础
  • 学习shell,这一篇就够了(shell基础)
    目录 一、shell概述 二、shell脚本准备知识 三、条件判断 四、结尾 一、shell概述 1、什么是shell shell是一种命令语言,是为使用者提供操作界面的一种软件,软件可以接收...
    99+
    2023-09-25
    linux centos 运维 网络 服务器
  • tornado学习笔记
    一.UIMOTHODS: 1.在项目目录创建uimothods.py文件(名称可以任意)内容: def test2(self): return ('hello uimothods')2.tornado项目文件中导入并注册: #导入f...
    99+
    2023-01-30
    学习笔记 tornado
  • python 基础学习
    #此代码关于python函数调用的理解学习#还不明白这段代码如何实现调用的!!!def apply_twice(func, arg):return func(func(arg)) def add_five(x):return x + 5 p...
    99+
    2023-01-31
    基础 python
  • HoneyDrive_3基础学习
    20161219 08:51——09:30 这篇博文记录HoneyDrive_3_Royal_Jelly(1)系统应用整体的简介和(2)初期准备或相关具体功能的介绍说明,和(3)HoneyDrive_3的基本使用或基础理论。参考:Honey...
    99+
    2023-01-31
    基础
  • PHP基础学习
    第一章、PHP基础 PHP是一种适合Web开发的编程语言,运行于服务器端,可以在C/S架构中为客户端软件提供服务器接口,又可以在B/S上作为架构来搭建动态网站。(本篇文章以B/S架构为基础) Apache为PHP提供工作环境 Apache ...
    99+
    2023-09-12
    php 学习 开发语言
  • Python基础学习
    第一个 Python 程序:Hello Worldprint("Hello World!")Python 控制流:if-else, if-elif-else:    if-else 语法:if 判断条件:     执行语句…… else: ...
    99+
    2023-01-31
    基础 Python
  • objective-c 基础学习
    目录 第一节:OC 介绍 ​​第二节:Fundation 框架 ​第三节:NSLog 相对于print 的增强 ​第四节:NSString ​第五节:oc新增数据类型 第六节: 类和对象 ​类的方法的声明与实现 ​第七节:类和对象的存储 ...
    99+
    2023-10-12
    objective-c 学习 开发语言
  • python基础学习2
    一.算数运算符 +加法,-减法,*乘法,/除法,//地板除,%求余,**幂运算。 二.逻辑运算符 非not、且and、或or。优先级依次为not,and,or。 三.print()end结尾 print()#默认为print(end="...
    99+
    2023-01-30
    基础 python
  • Python基础学习(二)
    Python函数总结 一、函数的基本用法 1、概念: 函数是对程序逻辑进行结构化或是过程化的一种编程方法,其是组织好的,可重复使用的,用来实现单一,或者相同功能的代码段。 函数提高了应用点的模块性和代码的重复利用率 本质:函数是对功...
    99+
    2023-01-30
    基础 Python
  • python基础学习3_if_for
    if用于条件判断,如果满足条件就执行否则就继续直到结束,熟悉shell条件判断就觉得so easy格式:if condition1:  execute commandelif condition2:  execute commandelse...
    99+
    2023-01-31
    基础 python _if_for
  • python基础学习1
    一.python第一个程序 print("hello world") 二.变量的命名规则   1. 字母数字下划线组成  2. 不能以数字开头,不能含有特殊字符和空格  3. 不能以保留字命名  4. 不能以中文命名  5. 定义的...
    99+
    2023-01-30
    基础 python
  • Python学习 :socket基础
     socket基础   什么是socket?   - socket为接口通道,内部封装了IP地址、端口、协议等信息;我们可以看作是以前的通过电话机拨号上网的年代,socket即为电话线   socket通信流程   我们通过下面的图来了解...
    99+
    2023-01-31
    基础 Python socket
  • python学习-4 python基础-
    条件语句的原理:     2.举个例子:比大小   #!/usr/bin/env python # -*- coding:utf8 -*- a=input("请输入a:") b=input("请输入b:") if a >...
    99+
    2023-01-31
    基础 python
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作