tornado

news2024/12/26 14:09:20

Tornado通过使用非阻塞网络1/0,可以扩展到数以万计的开放链接,非常适合 长时间轮询,WebSockets和其他需要与每个用户建立长期连接的应用程序。

特点

  • 注重性能优越,速度快
  • 解决高并发
  • 异步非阻塞
  • websockets 长连接
  • 内嵌了HTTP服务器
  • 单线程的异步网络程序,默认启动时根据CPU数量运行多个实例:利用CPU多核的优势

pip3 install tornado 

文档

 main.py

import tornado.web
import tornado.ioloop
from tornado.options import parse_command_line, options, define


class HelloHandler(tornado.web.RequestHandler):
    def get(self, *args, **kwargs):
        self.write('hello tornado')


def create_app():
    '''创建app, 注册路由与处理类'''
    app = tornado.web.Application(handlers=[
        (r'/', HelloHandler)
    ],
        template_path='templates',   # 模板文件的目录
        static_path='static',    # 告诉tornado 静态目录
        static_url_prefix='/static/'   # 浏览器访问时的url
    )
    return app

if __name__ == '__main__':
    # define, options, parse_command_line 三个配合使用解析命令行
    # 定义默认参数  这里定义默认启动端口,可通过命令行启动时修改port的值,改变端口
    define('port', default=8080, type=int)

    # 解析命令行
    parse_command_line()  # 获取命令行启动时 --xx  参数和值
    # 创建app
    app = create_app()
    # 监听端口
    app.listen(options.port)
    # python main.py --port=8080  # options.port 的值为 8080
    # 服务监听
    tornado.ioloop.IOLoop.instance().start()

请求

get请求

# http://127.0.0.1:8080/?name=asd&name=qwe

class HelloHandler(tornado.web.RequestHandler):
    def get(self):
        # 获取请求头信息
        user_agent = self.request.headers.get('User-Agent', 'Unknown')

        name = self.request.arguments.get('name')  # 当url有相同参数时,值为列表
        # ['asd', 'qwe']
        name = self.get_arguments('name')  # 当url有相同参数时,值为列表
        # ['asd', 'qwe']
        name = self.get_argument('name')
        name = self.get_query_argument('name')
        name = self.get_query_arguments('name')
        print(name)  # qwe
        self.write('hello word')

app = tornado.web.Application(handlers=[
        (r'/', HelloHandler)
    ])
# http://127.0.0.1:8080/api/user/12

class HelloHandler(tornado.web.RequestHandler):
    def get(self, uid):

        self.write(f'user id is: {uid}')

app = tornado.web.Application(handlers=[
        (r'/api/user/(\d+)', HelloHandler)
    ])

post请求

form-data请求的参数值在

  • self.request.arguments
  • self.request.body_arguments

json提交的数据再body中

  • self.request.body  # 需要json反序列化

urlencoded 请求的参数值在

  • self.request.arguments
  • self.request.body_arguments

class HelloHandler(tornado.web.RequestHandler):

    def post(self):
        # 获取form-data, urlencoded 参数
        name = self.request.arguments.get('name')
        name = self.get_argument('name')
        name = self.get_arguments('name')
        name = self.get_body_argument('name')
        name = self.get_body_arguments('name')
        
        # 获取json参数
        print(json.loads(self.request.body))

        self.write('post')

响应

write返回字符串

class HelloHandler(tornado.web.RequestHandler):
    def get(self, *args, **kwargs):
        self.write('hello tornado')

write返回json

  • 注意:自己手动序列化json方式 前端response headers 中的 Content_Type属性text/html,而采用write自动序列化方式,Content_Type属性为application/json
class HelloHandler(tornado.web.RequestHandler):
    def get(self, *args, **kwargs):
        data = {
            'name': 'alex',
            'age': 20,
            'hobby': ['python', 'go', 'java', 'c++']
        }
        # 自动序列化
        self.write(data)  # {"name": "alex", "age": 20, "hobby": ["python", "go", "java", "c++"]}


class HelloHandler(tornado.web.RequestHandler):
    def get(self, *args, **kwargs):
        data = {
            'name': 'alex',
            'age': 20,
            'hobby': ['python', 'go', 'java', 'c++']
        }
        # 手动json序列化, 需设置header: Content_Type属性text/html
        self.write(json.dumps(data))

set_header设置响应头

还有 clear_header,add_header 方法

class HelloHandler(tornado.web.RequestHandler):
    def get(self, *args, **kwargs):
        data = {
            'name': 'alex',
            'age': 20,
            'hobby': ['python', 'go', 'java', 'c++']
        }
        self.set_header("Content-Type","application/json;charset=UTF-8")
        self.set_header("token", "xxxxxxxxxxxx")
        self.write(data)

set_default_headers

规范默认修改响应的头的位置

  • 注意: 在http处理方法中再使用 self.set_headers() 方法 设置通用的name的值,会覆盖原先在set_default_headers() 中设置的值
class HelloHandler(tornado.web.RequestHandler):
    def set_default_headers(self):
        self.set_header("Content-Type","application/json;charset=UTF-8")
        self.set_header("token", "xxxxxxxxxxxx")
        
    def get(self, *args, **kwargs):
        data = {
            'name': 'alex',
            'age': 20,
            'hobby': ['python', 'go', 'java', 'c++']
        }
        self.set_header("token", "aaaaaaaaaaaa")  # 替换set_default_headers中设置的 token
        self.write(data)

set_status设置响应状态码

参数:

  • status--状态码的值为 int类型
  • reason--对状态码的描述 str类型 如果reason值为None 则状态码的值必须为正常值
class HelloHandler(tornado.web.RequestHandler):

    def get(self, *args, **kwargs):
        self.set_status(404)
        self.write('error')

redirect重定向

class HelloHandler(tornado.web.RequestHandler):

    def get(self, *args, **kwargs):
        self.write('hello tornado')


class UserHandler(tornado.web.RequestHandler):
    def get(self, *args, **kwargs):
        self.redirect('/')

app = tornado.web.Application(handlers=[
        (r'/', HelloHandler),
        (r'/user', UserHandler)
    ])

send_error

  • 作用:可以跑出http错误状态码,默认为500,跑出错误后tornado会调用write_error()方法处理,并返回给浏览器界面
  • 注意: 不执行send_error之后的内容
class HelloHandler(tornado.web.RequestHandler):

    def get(self, *args, **kwargs):
        self.send_error(500, reason="server error")
        # send_error 之后的代码不会执行
        self.write('hello tornado')

write_error(status_code,**kwargs)

  • 用来处理send_error跑出来的额信息,并返回给浏览器错误页面
class HelloHandler(tornado.web.RequestHandler):
    def write_error(self, status_code: int, **kwargs: Any):
        '''一般是返回自定义页面'''
        code = 200
        if status_code == 404:
            code = 404
            self.write('资源错误')
        elif status_code == 500:
            code = 500
            self.write('服务器错误')
        self.set_status(code)

    def get(self, *args, **kwargs):
        if self.get_argument('name') != 'alex':
            self.send_error(404)
        self.write('hello tornado')

finish

self.finish()RequestHandler 的一个方法,用于明确地结束 HTTP 请求处理。当你调用 self.finish() 时,Tornado 会立即发送响应给客户端,并关闭与该请求相关的所有资源。这意味着在 self.finish() 被调用之后,你不能再向响应中写入任何数据。

self.finish() 的主要用途包括:

  1. 提前终止响应:如果你在处理过程中发现不需要进一步处理或已经完成了所有的处理逻辑,可以调用 self.finish() 来立即发送响应并结束处理过程。

  2. 异步处理完成后的清理:在使用异步操作(如数据库查询、网络请求等)时,一旦操作完成,你可以调用 self.finish() 来结束请求处理。

  3. 防止意外的数据写入:通过显式调用 self.finish(),你可以确保不会在无意中向已发送的响应中添加额外的数据,这有助于避免产生不完整或损坏的响应。

文件上传下载


class UploadHandler(tornado.web.RequestHandler):
    def post(self):
        # 检查是否上传了文件
        if not self.request.files:
            self.write("No file uploaded")
            return

        # 获取文件对象
        file_info = self.request.files['file'][0]
        filename, content_type = file_info['filename'], file_info['content_type']
        body = file_info['body']

        # 定义保存路径
        upload_path = "files"
        if not os.path.exists(upload_path):
            os.makedirs(upload_path)

        # 保存文件
        with open(os.path.join(upload_path, filename), 'wb') as f:
            f.write(body)

        self.write(f"File {filename} has been uploaded successfully.")

class DownloadHandler(tornado.web.RequestHandler):
    def get(self, filename):
        # 文件路径
        dir_path = "files/"
        file_path = os.path.join(dir_path, filename)

        # 检查文件是否存在
        if not os.path.exists(file_path):
            raise tornado.web.HTTPError(404, "File not found")

        # 设置响应头
        self.set_header('Content-Type', 'application/octet-stream')
        self.set_header('Content-Disposition', f'attachment; filename="{filename}"')

        # 读取并发送文件
        with open(file_path, 'rb') as f:
            while True:
                data = f.read(16384)  # 一次读取16KB
                if not data:
                    break
                self.write(data)
        self.finish()



app = tornado.web.Application(handlers=[
        (r'/upload', UploadHandler),
        (r'/download/(.*)', DownloadHandler),

    ])

返回图片

import os
import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        # 显示包含图片链接的页面
        self.render("index.html")

class ImageHandler(tornado.web.RequestHandler):
    def get(self, filename):
        # 图片路径
        image_path = os.path.join("static", "images", filename)

        # 检查图片是否存在
        if not os.path.exists(image_path):
            raise tornado.web.HTTPError(404, "Image not found")

        # 设置响应头
        self.set_header('Content-Type', 'image/jpeg')  # 根据图片类型设置 Content-Type
        with open(image_path, 'rb') as f:
            while True:
                data = f.read(16384)  # 一次读取16KB
                if not data:
                    break
                self.write(data)
        self.finish()

def make_app():
    return tornado.web.Application([
        (r"/", MainHandler),
        (r"/image/(.*)", ImageHandler),  # 匹配/image/后面的所有内容作为图片文件名
        (r"/static/(.*)", tornado.web.StaticFileHandler, {"path": "static"}),  # 静态文件服务
    ], template_path=os.path.join(os.path.dirname(__file__), "templates"))

if __name__ == "__main__":
    app = make_app()
    app.listen(8080)
    print("Server started on port 8080")
    tornado.ioloop.IOLoop.current().start()

web框架-tornado操作数据库 - 简书

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2156218.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

jdk11特性介绍

JDK 11(也称为Java 11)是Java平台的一个重要版本,它引入了许多新特性和改进,旨在提高开发者的生产力和Java平台的性能。以下是一些JDK 11的主要特性: 局部变量类型推断(Local-Variable Syntax for Lambda P…

VMWare虚拟机安装CentOS-7-x86_64-DVD-1611操作系统

VMWare虚拟机安装CentOS7操作系统 1、虚拟机准备打开VMware单机创建新的虚拟机典型与自定义安装选择虚拟机硬件兼容性选择安装程序光盘映射文件(iso)选择客户机操作系统命名虚拟机处理器配置内存配置网络连接类型I/O类型选择磁盘类型选择磁盘指定磁盘的最大磁盘大小磁盘名称我们…

【Python报错已解决】TypeError: ‘<‘ not supported between instances of ‘str‘ and ‘int‘

🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 专栏介绍 在软件开发和日常使用中,BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

element-ui 日期选择器禁用某段特定日期

element-ui 日期选择器设置禁用日期 效果图如下: 2024-09-01 到2024-09-18之间的日期都不可选 2024-01-01之前的日期都不可选 官方文档中 picker-options 相关的介绍 实现功能: ​ 某仓库有限制最大可放置资产数量,且资产出借和存放都有记录。由于线下仓库资产出借和购…

Card View 卡片视图

Goto 数据网格和视图入门 Card View 卡片视图 The Card View displays data records as cards, arranged down and then across. Card fields are always arranged in a single column. The Card View is represented by the CardView class. Card View (卡片视图…

2024 SNERT 预备队招新 CTF 体验赛-Web

目录 1、robots 2、NOF12 3、get_post 4、好事慢磨 5、uploads 6、rce 7、ezsql 8、RCE 1、robots robots 协议又叫爬虫协议,访问 robots.txt 继续访问 /JAY.php 拿到 flag:flag{hello_Do_YOU_KONw_JAY!} 2、NOF12 F12 和右键都被禁用 方法&#…

[Linux]用户管理指令

开机/重启/登录/注销 进入xhsell 或者虚拟系统中, 右键桌面打开终端, 在终端执行命令, 重启或关机linux系统 建议使用普通账号登录, 如果权限不够时, 使用 su - 用户名 命令切换到超管, 然后再使用 logout命令退回到普通账号, logout 不能在图形界面的终端中使用 用户管理 Li…

Python画笔案例-058 绘制单击画酷炫彩盘

1、绘制单击画酷炫彩盘 通过 python 的turtle 库绘制 单击画酷炫彩盘,如下图: 2、实现代码 绘制单击画酷炫彩盘,以下为实现代码: """单击画酷炫彩盘.py"""from turtle import Turtle # 导入海龟类 from random import randint…

电子设计入门教程硬件篇之三极管BJT(四)

前言:本文为手把手教学的电子设计入门教程硬件类的博客,该博客侧重针对电子设计中的硬件电路进行介绍。本篇博客将根据电子设计实战中核心器件之一的三极管进行详细讲解,包含:PNP型与NPN型三极管。电子设计实践中的三极管是嵌入式…

心理教育辅导系统:Spring Boot技术实现

4 系统设计 4.1系统概要设计 高校心理教育辅导系统主要分为管理员、教师和学生三个角色,系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式,是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任…

xhs 小红书 x-s web 分析

声明: 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 有相关问题请第一时间头像私信联系我…

TryHackMe 第3天 | Pre Security (二)

该学习路径讲解了网络安全入门的必备技术知识,比如计算机网络、网络协议、Linux命令、Windows设置等内容。上一篇中简短介绍了计算机网络相关的知识,本篇博客将记录 网络协议 部分。 How the web works? DNS in detail DNS (Domain name system&…

19 基于51单片机的倒计时音乐播放系统设计

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 五个按键,分别为启动按键,则LCD1602显示倒计时,音乐播放 设置按键,可以设置倒计时的分秒,然后加减按键,还有最后一个暂停音乐…

基于 Web 的工业设备监测系统:非功能性需求与标准化数据访问机制的架构设计

目录 案例 【说明】 【问题 1】(6 分) 【问题 2】(14 分) 【问题 3】(5 分) 【答案】 【问题 1】解析 【问题 2】解析 【问题 3】解析 相关推荐 案例 阅读以下关于 Web 系统架构设计的叙述,回答问题 1 至问题 3 。 【说明】 某公司拟开发一款基于 Web 的…

BERT的代码实现

目录 1.BERT的理论 2.代码实现 2.1构建输入数据格式 2.2定义BERT编码器的类 2.3BERT的两个任务 2.3.1任务一:Masked Language Modeling MLM掩蔽语言模型任务 2.3.2 任务二:next sentence prediction 3.整合代码 4.知识点个人理解 1.BERT的理论 B…

代码随想录算法训练营第58天|卡码网 117. 软件构建、47. 参加科学大会

1. 卡码网 117. 软件构建 题目链接:https://kamacoder.com/problempage.php?pid1191 文章链接:https://www.programmercarl.com/kamacoder/0117.软件构建.html 思路:使用BFS BFS的实现思路: 拓扑排序的过程,其实就两步…

Java : 图书管理系统

图书管理系统的作用: 高效的图书管理 图书管理系统通过自动化管理,实现了图书的采编、编目、流通管理等操作的自动化处理,大大提高了图书管理的效率和准确性。 工作人员可以通过系统快速查找图书信息,实时掌握图书的借还情况&…

经典报童问题的2类扩展实例:带广告的报童问题和多产品报童问题

文章目录 1 引言2 经典报童问题3 带广告的报童问题3.1 论文解读3.2 样本均值近似方法 4 多产品报童问题4.1 论文解读4.2 算法模型4.3 简单实例求解4.4 复杂实例求解 5 总结6 相关阅读 1 引言 中秋已过,国庆未至,趁着这个空窗期,学点新知识&a…

解决DockerDesktop启动redis后采用PowerShell终端操作

如图: 在启动redis容器后,会计入以下界面 : 在进入执行界面后如图: 是否会觉得界面过于单调,于是想到使用PowerShell来操作。 步骤如下: 这样就能使用PowerShell愉快地敲命令了(颜值是第一生…

AttributeError: ‘Sequential‘ object has no attribute ‘predict_classes‘如何解决

今天跟着书敲代码,报错: Sequential object has no attribute predict_classes,如图所示: 上网百度,发现predict_classes函数在新版本中已经删除了,需要使用 model.predict() 替代 model.predict_classes()…