tornado

ops/2024/12/22 18:03:20/

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

特点

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

pip3 install tornado 

文档

 main.py

python">import tornado.web
import tornado.ioloop
from tornado.options import parse_command_line, options, defineclass 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 appif __name__ == '__main__':# define, options, parse_command_line 三个配合使用解析命令行# 定义默认参数  这里定义默认启动端口,可通过命令行启动时修改port的值,改变端口define('port', default=8080, type=int)# 解析命令行parse_command_line()  # 获取命令行启动时 --xx  参数和值# 创建appapp = create_app()# 监听端口app.listen(options.port)# python main.py --port=8080  # options.port 的值为 8080# 服务监听tornado.ioloop.IOLoop.instance().start()

请求

get请求

python"># http://127.0.0.1:8080/?name=asd&name=qweclass 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)  # qweself.write('hello word')app = tornado.web.Application(handlers=[(r'/', HelloHandler)])
python"># http://127.0.0.1:8080/api/user/12class 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

python">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返回字符串

python">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
python">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/htmlself.write(json.dumps(data))

set_header设置响应头

还有 clear_header,add_header 方法

python">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() 中设置的值
python">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中设置的 tokenself.write(data)

set_status设置响应状态码

参数:

  • status--状态码的值为 int类型
  • reason--对状态码的描述 str类型 如果reason值为None 则状态码的值必须为正常值
python">class HelloHandler(tornado.web.RequestHandler):def get(self, *args, **kwargs):self.set_status(404)self.write('error')

redirect重定向

python">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之后的内容
python">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跑出来的额信息,并返回给浏览器错误页面
python">class HelloHandler(tornado.web.RequestHandler):def write_error(self, status_code: int, **kwargs: Any):'''一般是返回自定义页面'''code = 200if status_code == 404:code = 404self.write('资源错误')elif status_code == 500:code = 500self.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(),你可以确保不会在无意中向已发送的响应中添加额外的数据,这有助于避免产生不完整或损坏的响应。

文件上传下载

python">
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)  # 一次读取16KBif not data:breakself.write(data)self.finish()app = tornado.web.Application(handlers=[(r'/upload', UploadHandler),(r'/download/(.*)', DownloadHandler),])

返回图片

python">import os
import tornado.ioloop
import tornado.webclass 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-Typewith open(image_path, 'rb') as f:while True:data = f.read(16384)  # 一次读取16KBif not data:breakself.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.ppmy.cn/ops/117255.html

相关文章

桶排序和计数排序(非比较排序算法)

桶排序 桶排序是一种基于分配的排序算法,特别适合用来排序均匀分布的数据。它的基本思想是将输入的数据分到有限数量的桶里,然后对每个桶内的数据分别进行排序,最后再将各个桶内的数据合并得到最终的排序结果。(通常用于浮点数,因…

3.javaweb-Servlet与过滤器

javaweb-Servlet与过滤器 文章目录 javaweb-Servlet与过滤器一、Servlet:server applet二、Servlet做了什么?三、Servlet是什么?四、jsp与Servlet关系五、Servlet API1.主要Servlet API介绍2.如何创建Servlet3.Servlet中主要方法4.ServletReq…

零成本玩转企业微信!2024年邮箱功能新升级,速来get√

在这个网络时代,公司聊天和管理得快不快,对公司能不能赢很关键。企业微信是腾讯给公司做的聊天和办公工具,因为功能多、用着方便,很多公司都喜欢用。不过,新用企业微信的公司最想知道的是:用这个要不要花钱…

Spring Boot 点餐系统:高效餐饮服务

第二章关键技术的研究 2.1相关技术 网上点餐系统是在Java MySQL开发环境的基础上开发的。Java是一种服务器端脚本语言,易于学习,实用且面向用户。全球超过35%的Java驱动的互联网站点使用Java。MySQL是一个数据库管理系统,因为它的…

近万字深入讲解iOS常见锁及线程安全

什么是锁? 在程序中,当多个任务(或线程)同时访问同一个资源时,比如多个操作同时修改一份数据,可能会导致数据不一致。这时候,我们需要“锁”来确保同一时间只有一个任务能够操作这个数据&#…

ELFK日志分析平台,架构和通信

整个架构,加上跳板机,总共12台机器 技术方案: 1. 配置nfs服务器,为web集群提供共享网络文件系统 # 部署 NFS 服务 [rootnfs ~]# dnf install -y nfs-utils [rootnfs ~]# vim /etc/exports /var/webroot 192.168.1.0/24(rw,…

STM32篇:STM32CubeMX的安装

一.介绍与安装 1.作用 通过界面的方式,快速生成工程文件。 2.下载 官网 https://www.st.com/zh/development-tools/stm32cubemx.html#overview 3.安装 一路下一步,建议不要安装在C盘 4.配置 更新固件包位置(比较大,默认在…

SpringBoot 项目打成 jar 后加载外部的配置文件

Spring Boot应用最大的特点就是使用配置来代替编码,很多时候启用某一个功能只需要引入相关的starter,再加入对应的配置项就可以了,例如数据源,安全性,中间件等等。对于单个项目,我们一般会把配置项放到appl…