阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

tornado基础

439次阅读
没有评论

共计 6418 个字符,预计需要花费 17 分钟才能阅读完成。

一、第一个 tornado 程序

  • 新建文件 manage.py 代码如下

    import tornado.web import tornado.ioloop class IndexHandler(tornado.web.RequestHandler): """主路由处理类""" def get(self): """对应 http 的 get 请求方式""" self.write("Hello Lucky!") if __name__ == "__main__": app = tornado.web.Application([(r"/", IndexHandler), ]) app.listen(8000) tornado.ioloop.IOLoop.current().start()
  • 运行

    python manage.py

  • 请求

    打开浏览器,输入网址 127.0.0.1:8000(或 localhost:8000)

tornado 基础

  • 代码讲解

    • tornado.web

      tornado 的基础 web 框架模块

    • RequestHandler

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

      我们将代码中定义的 get() 方法更改为 post() 后,再用浏览器重新访问(浏览器地址栏中输入网址访问的方式为 get 请求方式)

      示例

      import tornado.web import tornado.ioloop class IndexHandler(tornado.web.RequestHandler): """主路由处理类""" def post(self): # 修改方式为 POST """对应 http 的 post 请求方式""" self.write("Hello Lucky!") if __name__ == "__main__": ...

      访问

tornado 基础

  • Application

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

    注意:此时服务器并未开启监听

  • tornado.ioloop

    tornado 的核心 io 循环模块,封装了 Linux 的 epoll 和 BSD 的 kqueue,tornado 高性能的基石

  • IOLoop.current()

    返回当前线程的 IOLoop 实例

  • IOLoop.start()

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

  • 步骤

    • 创建 web 应用实例对象,第一个初始化参数为路由映射列表
    • 定义实现路由映射列表中的 handler 类
    • 创建服务器实例,绑定服务器端口
    • 启动当前线程的 IOLoop

二、httpserver

  • 概述

    之前我们通过创建了一个 http 服务器示例并绑定到给定端口(tornado.web.Application.listen(800))接下来进行手动实现

  • 代码

    import tornado.web import tornado.ioloop import tornado.httpserver # 导入 httpserver 模块 class IndexHandler(tornado.web.RequestHandler): """主路由处理类""" def get(self): """对应 http 的 get 请求方式""" self.write("Hello Lucky!") if __name__ == "__main__": app = tornado.web.Application([(r"/", IndexHandler), ]) # 我们修改这个部分 # app.listen(8000) http_server = tornado.httpserver.HTTPServer(app) http_server.listen(8000) tornado.ioloop.IOLoop.current().start()
  • 说明

    在当前代码中,我们引入了 tornado.httpserver 模块,顾名思义,它就是 tornado 的 HTTP 服务器实现

    我们创建了一个 HTTP 服务器实例 http_server,因为服务器要服务于我们刚刚建立的 web 应用,将接收到的客户端请求通过 web 应用中的路由映射表引导到对应的 handler 中,所以在构建 http_server 对象的时候需要传出 web 应用对象 app。http_server.listen(8000) 将服务器绑定到 8000 端口

    实际上一版代码中 app.listen(8000) 正是对这一过程的简写

三、单进程与多进程

  • 我们刚刚实现的都是单进程,可以通过命令来查看进程

    ps -ef | grep manage.py
    

tornado 基础

  • 启动多个进程 修改代码如下

    import tornado.web import tornado.ioloop import tornado.httpserver class IndexHandler(tornado.web.RequestHandler): """主路由处理类""" def get(self): """对应 http 的 get 请求方式""" self.write("Hello lucky!") if __name__ == "__main__": app = tornado.web.Application([(r"/", IndexHandler), ]) http_server = tornado.httpserver.HTTPServer(app) # 修改 http_server.bind(8000) http_server.start(0) tornado.ioloop.IOLoop.current().start()

    代码是说明

    • http_server.bind(port) 方法是将服务器绑定到指定端口
    • http_server.start(num_processes=1) 方法指定开启几个进程
      • 参数 num_processes 默认值为 1,即默认仅开启一个进程
      • num_processes 为 None 或者 <=0,则自动根据机器硬件的 cpu 核芯数创建同等数目的子进程
      • num_processes>0,则创建 num_processes 个子进程
  • 上段代码中,我们使用 http_server.start(0),而我的 Mac cpu 核数为 8

    演示结果

tornado 基础

  • 注意

    我们在前面写的 http_server.listen(8000) 实际上就等同于

    http_server.bind(8000)
    http_server.start(1)
    

四、注意

  • 关于 app.listen()

    app.listen() 这个方法只能在单进程模式中使用

    对于 app.listen() 与手动创建 HTTPServer 实例

    http_server = tornado.httpserver.HTTPServer(app) http_server.listen(8000)

    这两种方式,建议大家先使用后者即创建 HTTPServer 实例的方式,因为其对于理解 tornado web 应用工作流程的完整性有帮助,便于大家记忆 tornado 开发的模块组成和程序结构;在熟练使用后,可以改为简写

  • 关于多进程

    虽然 tornado 给我们提供了一次开启多个进程的方法,但是由于:

    • 每个子进程都会从父进程中复制一份 IOLoop 实例,如过在创建子进程前我们的代码动了 IOLoop 实例,那么会影响到每一个子进程,势必会干扰到子进程 IOLoop 的工作
    • 所有进程是由一个命令一次开启的,也就无法做到在不停服务的情况下更新代码
    • 所有进程共享同一个端口,想要分别单独监控每一个进程就很困难

    不建议使用这种多进程的方式,而是手动开启多个进程,并且绑定不同的端口

五、options

  • 说明

    在前面的示例中我们都是将服务端口的参数写死在程序中,很不灵活

    tornado 为我们提供了一个便捷的工具,tornado.options 模块——全局参数定义、存储、转换

  • tornado.options.define()

    • 说明

      用来定义 options 选项变量的方法,定义的变量可以在全局的 tornado.options.options 中获取使用

    • 参数

      • name

        选项变量名,须保证全局唯一性,否则会报 ”Option‘xxx’already defined in …” 的错误

      • default

        选项变量的默认值,如不传默认为 None

      • type

        选项变量的类型,从命令行或配置文件导入参数的时候 tornado 会根据这个类型转换输入的值,转换不成功时会报错,可以是 str、float、int、datetime、timedelta 中的某个,若未设置则根据 default 的值自动推断,若 default 也未设置,那么不再进行转换。可以通过利用设置 type 类型字段来过滤不正确的输入

      • multiple

        选项变量的值是否可以为多个,布尔类型,默认值为 False,如果 multiple 为 True,那么设置选项变量时值与值之间用英文逗号分隔,而选项变量则是一个 list 列表(若默认值和输入均未设置,则为空列表 [])

      • help

        选项变量的帮助提示信息,在命令行启动 tornado 时,通过加入命令行参数 –help 可以查看所有选项变量的信息(注意,代码中需要加入 tornado.options.parse_command_line())

  • tornado.options.options

    • 说明

      全局的 options 对象,所有定义的选项变量都会作为该对象的属性。

  • tornado.options.parse_command_line()

    • 说明

      转换命令行参数,并将转换后的值对应的设置到全局 options 对象相关属性上。追加命令行参数的方式是–myoption=myvalue

    • 使用

      新建 manage2.py,我们用代码来看一下如何使用

      import tornado.web import tornado.ioloop import tornado.httpserver import tornado.options # 新导入的 options 模块 tornado.options.define("port", default=8000, type=int, help="run server on the given port.") # 定义服务器监听端口选项 tornado.options.define("lucky", default=[], type=str, multiple=True, help="lucky is a good man") # 无意义,演示多值情况 class IndexHandler(tornado.web.RequestHandler): """主路由处理类""" def get(self): """对应 http 的 get 请求方式""" self.write("Hello Itcast!") if __name__ == "__main__": tornado.options.parse_command_line() print(tornado.options.options.lucky) # 输出多值选项 print(tornado.options.options.port) # 输出多值选项 app = tornado.web.Application([(r"/", IndexHandler), ]) http_server = tornado.httpserver.HTTPServer(app) http_server.listen(tornado.options.options.port) tornado.ioloop.IOLoop.current().start()

      执行如下命令开启程序:

      python manage2.py --port=9000 --lucky=handsome,Sunshine,Sunshine

      查看帮助

      python manage2.py --help

      效果如下:

tornado 基础

  • tornado.options.parse_config_file(path)

    从配置文件导入 option,配置文件中的选项格式如下

    myoption = "myvalue" myotheroption = "myothervalue"

    我们用代码来看一下如何使用,新建配置文件 config.py,注意字符串和列表按照 python 的语法格式:

    port = 8000 lucky = ["handsome","Sunshine","Sunshine"]

    修改 manage2.py 文件:

    ... if __name__ == "__main__": # 仅仅修改了此处 tornado.options.parse_config_file("./config.py") ...

    tornado 基础

六、日志与配置

  • 日志

    当我们在代码中调用 parse_command_line() 或者 parse_config_file() 的方法时,tornado 会默认为我们配置标准 logging 模块,即默认开启了日志功能,并向标准输出(屏幕)打印日志信息

tornado 基础

如果想关闭 tornado 默认的日志功能,可以在命令行中添加–logging=none 或者在代码中执行如下操作

from tornado.options import parse_command_line parse_command_line()

命令

python manage.py --logging=none

添加在代码中关闭 logging

from tornado.options import options options.logging = None
  • 配置文件

    我们看到在使用 prase_config_file() 的时候,配置文件的书写格式仍需要按照 python 的语法要求,其优势是可以直接将配置文件的参数转换设置到全局对象 tornado.options.options 中;然而,其不方便的地方在于需要在代码中调用 tornado.options.define() 来定义选项,而且不支持字典类型,故而在实际应用中大都不使用这种方法。

    在使用配置文件的时候,通常会新建一个 python 文件(如 config.py),然后在里面直接定义 python 类型的变量(可以是字典类型);在需要配置文件参数的地方,将 config.py 作为模块导入,并使用其中的变量参数。

    config.py 文件:

    # Redis 配置 redis_options = {'redis_host':'127.0.0.1', 'redis_port':6379, 'redis_pass':'', } # Tornado app 配置 settings = {'template_path': os.path.join(os.path.dirname(__file__), 'templates'), # html 文件 'static_path': os.path.join(os.path.dirname(__file__), 'statics'), # 静态文件(css,js,img) 'cookie_secret':'0Q1AKOKTQHqaa+N80XhYW7KCGskOUE2snCW06UIxXgI=', # cookie 自定义字符串加盐 'xsrf_cookies':False, # 防止跨站伪造 'login_url':'/login', 'debug':True, } # 日志 log_path = os.path.join(os.path.dirname(__file__), 'logs/log')

    使用 config.py 的模块中导入 config,如下

    # conding:utf-8 import tornado.web import config if __name__ = "__main__": app = tornado.web.Application([], **config.settings) ...

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-05-26发表,共计6418字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

星哥玩云

星哥玩云
星哥玩云
分享互联网知识
用户数
4
文章数
19351
评论数
4
阅读量
7997450
文章搜索
热门文章
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见zabbix!轻量级自建服务器监控神器在Linux 的完整部署指南

再见 zabbix!轻量级自建服务器监控神器在 Linux 的完整部署指南 在日常运维中,服务器监控是绕不开的...
飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛 NAS 中安装 Navidrome 音乐文件中文标签乱码问题解决、安装 FntermX 终端 问题背景 ...
阿里云CDN
阿里云CDN-提高用户访问的响应速度和成功率
随机文章
开源MoneyPrinterTurbo 利用AI大模型,一键生成高清短视频!

开源MoneyPrinterTurbo 利用AI大模型,一键生成高清短视频!

  开源 MoneyPrinterTurbo 利用 AI 大模型,一键生成高清短视频! 在短视频内容...
国产开源公众号AI知识库 Agent:突破未认证号限制,一键搞定自动回复,重构运营效率

国产开源公众号AI知识库 Agent:突破未认证号限制,一键搞定自动回复,重构运营效率

国产开源公众号 AI 知识库 Agent:突破未认证号限制,一键搞定自动回复,重构运营效率 大家好,我是星哥,...
小白也能看懂:什么是云服务器?腾讯云 vs 阿里云对比

小白也能看懂:什么是云服务器?腾讯云 vs 阿里云对比

小白也能看懂:什么是云服务器?腾讯云 vs 阿里云对比 星哥玩云,带你从小白到上云高手。今天咱们就来聊聊——什...
从“纸堆”到“电子化”文档:用这个开源系统打造你的智能文档管理系统

从“纸堆”到“电子化”文档:用这个开源系统打造你的智能文档管理系统

从“纸堆”到“电子化”文档:用这个开源系统打造你的智能文档管理系统 大家好,我是星哥。公司的项目文档存了一堆 ...
零成本上线!用 Hugging Face免费服务器+Docker 快速部署HertzBeat 监控平台

零成本上线!用 Hugging Face免费服务器+Docker 快速部署HertzBeat 监控平台

零成本上线!用 Hugging Face 免费服务器 +Docker 快速部署 HertzBeat 监控平台 ...

免费图片视频管理工具让灵感库告别混乱

一言一句话
-「
手气不错
240 元左右!五盘位 NAS主机,7 代U硬解4K稳如狗,拓展性碾压同价位

240 元左右!五盘位 NAS主机,7 代U硬解4K稳如狗,拓展性碾压同价位

  240 元左右!五盘位 NAS 主机,7 代 U 硬解 4K 稳如狗,拓展性碾压同价位 在 NA...
浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍

浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍

浏览器自动化工具!开源 AI 浏览器助手让你效率翻倍 前言 在 AI 自动化快速发展的当下,浏览器早已不再只是...
星哥带你玩飞牛NAS硬件 01:捡垃圾的最爱双盘,暴风二期矿渣为何成不老神话?

星哥带你玩飞牛NAS硬件 01:捡垃圾的最爱双盘,暴风二期矿渣为何成不老神话?

星哥带你玩飞牛 NAS 硬件 01:捡垃圾的最爱双盘,暴风二期矿渣为何成不老神话? 前言 在选择 NAS 用预...
开发者福利:免费 .frii.site 子域名,一分钟申请即用

开发者福利:免费 .frii.site 子域名,一分钟申请即用

  开发者福利:免费 .frii.site 子域名,一分钟申请即用 前言 在学习 Web 开发、部署...
手把手教你,购买云服务器并且安装宝塔面板

手把手教你,购买云服务器并且安装宝塔面板

手把手教你,购买云服务器并且安装宝塔面板 前言 大家好,我是星哥。星哥发现很多新手刚接触服务器时,都会被“选购...