Tornado 与其他 Python Web 框架的对比
liebian365 2024-11-26 05:52 21 浏览 0 评论
谈到 Python Web 开发,有几个框架因其独特的功能和能力而脱颖而出。其中,Tornado 因注重高效处理异步操作而独树一帜。在这篇博文中,我们将 Tornado 与其他流行的 Python Web 框架(如 Flask、Django 和 FastAPI)进行比较,重点介绍每个框架的优势和用例。此外,我们还将提供一些实际演示来说明差异。
1. Tornado 概述
Tornado 是一个 Python Web 框架和异步网络库,最初由 FriendFeed 开发,后来被 Facebook 收购。它旨在处理异步操作和高性能应用程序,使其适用于需要处理大量同时连接的用例,例如 WebSockets 和长轮询。
Tornado 的主要特点:
- 非阻塞 I/O:Tornado 的非阻塞 I/O 是其性能的核心,使其能够高效处理数千个同时网络连接。
- WebSocket 支持:内置对 WebSocket 的支持使其成为实时应用程序的理想选择。
- 可扩展性:Tornado 的异步特性和事件驱动架构为高流量应用程序提供了出色的可扩展性。
- 内置服务器:与许多框架不同,Tornado 带有自己的 Web 服务器,该服务器针对处理异步请求进行了优化。
2. 将 Tornado 与其他框架进行比较
2.1 Tornado 与 Flask
Flask 是一个以简单性和灵活性而闻名的微框架。它非常适合不需要复杂异步操作的中小型应用程序。
- 简单性:Flask 采用简单而简约的方法,对初学者友好。它允许开发人员根据需要添加扩展。
- 同步特性:Flask 默认是同步的,除非使用其他工具进行管理,否则可能会导致在重负载下阻塞 I/O 操作。
- 用例:非常适合小型应用程序、REST API 和微服务,其中实时功能不是主要的需求。
演示:使用 Tornado 与 Flask 的简单 REST API
Flask 示例:
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/hello')
def hello():
return jsonify(message="Hello, World!")
if __name__ == '__main__':
app.run(debug=True)
Tornado 示例:
import tornado.ioloop
import tornado.web
class HelloHandler(tornado.web.RequestHandler):
def get(self):
self.write({"message": "Hello, World!"})
def make_app():
return tornado.web.Application([
(r"/hello", HelloHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
比较:Tornado 需要更多样板来设置路由和应用程序。但是,其非阻塞特性使其能够处理更多同时发生的请求。
2.2 Tornado 与 Django
Django 是一个全栈 Web 框架,遵循“batteries-included”理念。它提供了一系列现成的功能,例如 ORM、管理面板、身份验证等。
- 全面的功能:Django 包含开发复杂 Web 应用程序所需的一切。
- 同步设计:与 Flask 一样,Django 默认是同步的,这可能会限制高并发应用程序。
- 用例:最适合大型、数据库驱动的 Web 应用程序,快速开发和广泛的内置功能等诸多益处。
演示:使用 Tornado 与 Django 进行实时通知
Django(使用 Django 通道进行 WebSocket 通信):
# routing.py
from django.urls import path
from . import consumers
websocket_urlpatterns = [
path('ws/notifications/', consumers.NotificationConsumer.as_asgi()),
]
# consumers.py
from channels.generic.websocket import AsyncWebsocketConsumer
import json
class NotificationConsumer(AsyncWebsocketConsumer):
async def connect(self):
await self.accept()
async def disconnect(self, close_code):
pass
async def receive(self, text_data):
data = json.loads(text_data)
message = data['message']
await self.send(text_data=json.dumps({
'message': message
}))
Tornado:
import tornado.ioloop
import tornado.web
import tornado.websocket
class NotificationHandler(tornado.websocket.WebSocketHandler):
def open(self):
self.write_message("Connected to server.")
def on_message(self, message):
self.write_message(f"Received: {message}")
def on_close(self):
print("Connection closed")
def make_app():
return tornado.web.Application([
(r"/notifications", NotificationHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
比较:Django 需要额外的配置(如 Django Channels)才能支持 WebSockets,而 Tornado 原生支持它们,展示了 Tornado 在实时通信方面的实力。
2.3 Tornado 与 FastAPI
FastAPI 是一个使用 Python 构建 API 的现代、快速 Web 框架。它利用 Python 的异步功能和类型提示,使其成为高性能 API 的绝佳选择。
- 默认异步:FastAPI 使用 Python 的异步功能异步处理请求,类似于 Tornado。
- 自动文档:FastAPI 使用 Swagger 和 ReDoc 自动生成交互式 API 文档。
- 用例:非常适合构建支持异步编程、自动验证和交互式文档的现代 API。
演示:Tornado 与 FastAPI 的异步 API
FastAPI 示例:
from fastapi import FastAPI
app = FastAPI()
@app.get("/hello")
async def hello():
return {"message": "Hello, World!"}
Tornado 示例:
import tornado.ioloop
import tornado.web
class HelloHandler(tornado.web.RequestHandler):
async def get(self):
self.write({"message": "Hello, World!"})
def make_app():
return tornado.web.Application([
(r"/hello", HelloHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
比较:FastAPI 提供了一种更直接的方式来创建异步端点,减少样板代码。 Tornado 虽然也支持异步,但需要更多设置,并且不包含内置的交互式文档。
3. 选择正确的框架
何时使用 Tornado:
- 实时应用程序:在构建需要实时功能的应用程序(例如聊天应用程序)时,Tornado 的 WebSocket 支持和非阻塞 I/O 大放异彩。
- 处理长连接:Tornado 的异步功能使其成为需要维护许多长连接的应用程序的理想选择。
- 可扩展性和性能:Tornado 能够处理数千个同时连接,使其成为高流量应用程序的不二之选。
何时使用其他框架:
- Flask:对于需要灵活性而又不需要更复杂框架开销的简单、中小型应用程序,请选择 Flask。
- Django:在开发大型、功能丰富的 Web 应用程序时,选择 Django,因为内置功能和快速开发是优先事项。
- FastAPI:对于需要异步编程、自动验证和交互式文档的现代 API,请使用 FastAPI。
下面是一些额外的演示,重点介绍 Tornado 与其他 Python Web 框架之间的差异,重点介绍处理 HTTP 请求、与数据库集成以及实现中间件等方面。
1. 处理并发请求
Tornado 的一个关键优势是它能够高效处理大量并发连接。让我们将 Tornado 的方法与另一个异步框架 FastAPI 在处理并发请求方面进行比较。
演示:Tornado 与 FastAPI 的并发请求处理
Tornado 示例:
import tornado.ioloop
import tornado.web
import asyncio
class AsyncHandler(tornado.web.RequestHandler):
async def get(self):
await asyncio.sleep(2) # Simulate an async I/O operation
self.write("Request handled asynchronously")
def make_app():
return tornado.web.Application([
(r"/async", AsyncHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
FastAPI 示例:
from fastapi import FastAPI
import asyncio
app = FastAPI()
@app.get("/async")
async def read_async():
await asyncio.sleep(2) # Simulate an async I/O operation
return {"message": "Request handled asynchronously"}
比较:Tornado 和 FastAPI 都可以高效处理异步任务。Tornado 需要定义请求处理程序类,而 FastAPI 使用装饰器和异步函数,使 FastAPI 更简洁,更易于熟悉 Python 异步语法的开发人员理解。
2. 数据库集成
与数据库集成是 Web 应用程序中的常见要求。让我们比较一下 Tornado 和 Django 在处理数据库操作方面的表现。
演示:Tornado 与 Django 的数据库集成
Django 示例:
Django 有一个内置的 ORM,可以简化数据库操作。以下是定义模型并使用它来与 SQLite 数据库交互的方法:
# models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=100)
price = models.DecimalField(max_digits=10, decimal_places=2)
# views.py
from django.http import JsonResponse
from .models import Product
def product_list(request):
products = Product.objects.all().values()
return JsonResponse(list(products), safe=False)
Tornado 示例:
Tornado 没有内置 ORM,因此您可以使用 SQLAlchemy 等库与数据库交互:
from tornado.web import RequestHandler, Application
from tornado.ioloop import IOLoop
from sqlalchemy import create_engine, Column, Integer, String, Float
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
Base = declarative_base()
engine = create_engine('sqlite:///products.db')
Session = sessionmaker(bind=engine)
session = Session()
class Product(Base):
__tablename__ = 'products'
id = Column(Integer, primary_key=True)
name = Column(String(100))
price = Column(Float)
class ProductHandler(RequestHandler):
def get(self):
products = session.query(Product).all()
self.write({"products": [{"name": p.name, "price": p.price} for p in products]})
def make_app():
return Application([
(r"/products", ProductHandler),
])
if __name__ == "__main__":
Base.metadata.create_all(engine)
app = make_app()
app.listen(8888)
IOLoop.current().start()
比较:Django 的内置 ORM 高度集成到其框架中,使数据库操作无缝衔接。Tornado 需要额外设置才能集成 ORM,这提供了更大的灵活性,但也增加了复杂性。开发人员可以选择他们喜欢的数据库库,例如 SQLAlchemy 或 asyncpg,以满足特定要求。
3. 中间件支持
中间件对于请求日志记录、身份验证和错误处理等任务至关重要。以下是 Tornado 和 Flask 之间中间件实现的不同之处。
演示:Tornado 与 Flask 的中间件实现对比
Flask 示例:
在 Flask 中,可以使用 before_request 和 after_request 装饰器实现中间件:
from flask import Flask, request
app = Flask(__name__)
@app.before_request
def before_request():
print(f"Request received: {request.method} {request.url}")
@app.after_request
def after_request(response):
print(f"Request processed with status: {response.status}")
return response
@app.route("/hello")
def hello():
return "Hello, Flask with Middleware!"
if __name__ == "__main__":
app.run(debug=True)
Tornado 示例:
在 Tornado 中,可以使用自定义包装函数围绕请求处理程序来实现中间件:
import tornado.ioloop
import tornado.web
class BaseHandler(tornado.web.RequestHandler):
def prepare(self):
print(f"Request received: {self.request.method} {self.request.uri}")
def on_finish(self):
print(f"Request processed with status: {self.get_status()}")
class HelloHandler(BaseHandler):
def get(self):
self.write("Hello, Tornado with Middleware!")
def make_app():
return tornado.web.Application([
(r"/hello", HelloHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
比较:在 Flask 中,使用提供的钩子(before_request、after_request)可以轻松实现中间件。Tornado 是一个更底层的框架,允许通过类继承或包装处理程序来实现中间件。这提供了对请求处理的更多控制,但需要更多的样板代码。
4. 处理静态文件
高效地提供静态文件对于 Web 应用程序至关重要。让我们看看 Tornado 和 Django 如何处理静态文件。
演示:Tornado 与 Django 提供静态文件的比较
Django 示例:
Django 使用 STATIC_URL 设置和静态处理静态文件查看:
# settings.py
STATIC_URL = '/static/'
# urls.py
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# Other URL patterns
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Tornado 示例:
Tornado 可以通过在应用程序设置中指定 static_path 来提供静态文件:
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, Tornado!")
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
], static_path="static", static_url_prefix="/static/")
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
比较:Django 具有更多内置支持和结构化方法来提供静态文件,包括用于从不同位置收集静态文件的实用程序。Tornado 提供了更简单、更灵活的设置,适用于轻量级和自定义实现。
5. 错误处理
错误处理对于维护强大的 Web 应用程序至关重要。以下是 Tornado 和 FastAPI 中错误处理的方法。
演示:Tornado 与 FastAPI 的错误处理
FastAPI 示例:
FastAPI 使用 Python 的异常处理来优雅地管理错误:
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int):
if item_id < 1:
raise HTTPException(status_code=404, detail="Item not found")
return {"item_id": item_id}
Tornado 示例:
在 Tornado 中,通过重写 write_error 方法实现自定义错误处理:
import tornado.ioloop
import tornado.web
class ErrorHandler(tornado.web.RequestHandler):
def get(self, item_id):
if int(item_id) < 1:
self.send_error(404, message="Item not found")
else:
self.write({"item_id": item_id})
def write_error(self, status_code, **kwargs):
self.write({"error": kwargs.get("message", "Unknown error")})
def make_app():
return tornado.web.Application([
(r"/items/(\d+)", ErrorHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
比较:FastAPI 使用异常来管理错误,这更直观、更符合 Python 风格。Tornado 提供了一种更灵活但更冗长的方法,允许通过重写请求处理程序类中的方法自定义错误处理。
写在最后:
- 这些演示说明了 Tornado 与其他流行的 Python Web 框架(如 Flask、Django 和 FastAPI)相比的不同方法和优势。Tornado 在需要高并发性和实时通信的场景中表现出色,而 Flask 和 Django 则提供简单性和广泛的内置功能。FastAPI 以其现代异步功能和自动文档脱颖而出。了解这些差异可以帮助开发人员根据其特定的应用程序需求选择合适的工具。
- Tornado 是一个功能强大的框架,具有特定的用例,特别是在需要高并发性和实时通信的场景中。虽然它可能不像 Django 那样功能丰富,也不像 Flask 或 FastAPI 那样简单,但它的非阻塞特性和可扩展性使其成为开发人员工具包中有价值的工具。
相关推荐
- 4万多吨豪华游轮遇险 竟是因为这个原因……
-
(观察者网讯)4.7万吨豪华游轮搁浅,竟是因为油量太低?据观察者网此前报道,挪威游轮“维京天空”号上周六(23日)在挪威近海发生引擎故障搁浅。船上载有1300多人,其中28人受伤住院。经过数天的调...
- “菜鸟黑客”必用兵器之“渗透测试篇二”
-
"菜鸟黑客"必用兵器之"渗透测试篇二"上篇文章主要针对伙伴们对"渗透测试"应该如何学习?"渗透测试"的基本流程?本篇文章继续上次的分享,接着介绍一下黑客们常用的渗透测试工具有哪些?以及用实验环境让大家...
- 科幻春晚丨《震动羽翼说“Hello”》两万年星间飞行,探测器对地球的最终告白
-
作者|藤井太洋译者|祝力新【编者按】2021年科幻春晚的最后一篇小说,来自大家喜爱的日本科幻作家藤井太洋。小说将视角放在一颗太空探测器上,延续了他一贯的浪漫风格。...
- 麦子陪你做作业(二):KEGG通路数据库的正确打开姿势
-
作者:麦子KEGG是通路数据库中最庞大的,涵盖基因组网络信息,主要注释基因的功能和调控关系。当我们选到了合适的候选分子,单变量研究也已做完,接着研究机制的时便可使用到它。你需要了解你的分子目前已有哪些...
- 知存科技王绍迪:突破存储墙瓶颈,详解存算一体架构优势
-
智东西(公众号:zhidxcom)编辑|韦世玮智东西6月5日消息,近日,在落幕不久的GTIC2021嵌入式AI创新峰会上,知存科技CEO王绍迪博士以《存算一体AI芯片:AIoT设备的算力新选择》...
- 每日新闻播报(September 14)_每日新闻播报英文
-
AnOscarstatuestandscoveredwithplasticduringpreparationsleadinguptothe87thAcademyAward...
- 香港新巴城巴开放实时到站数据 供科技界研发使用
-
中新网3月22日电据香港《明报》报道,香港特区政府致力推动智慧城市,鼓励公私营机构开放数据,以便科技界研发使用。香港运输署21日与新巴及城巴(两巴)公司签署谅解备忘录,两巴将于2019年第3季度,开...
- 5款不容错过的APP: Red Bull Alert,Flipagram,WifiMapper
-
本周有不少非常出色的app推出,鸵鸟电台做了一个小合集。亮相本周榜单的有WifiMapper's安卓版的app,其中包含了RedBull的一款新型闹钟,还有一款可爱的怪物主题益智游戏。一起来看看我...
- Qt动画效果展示_qt显示图片
-
今天在这篇博文中,主要实践Qt动画,做一个实例来讲解Qt动画使用,其界面如下图所示(由于没有录制为gif动画图片,所以请各位下载查看效果):该程序使用应用程序单窗口,主窗口继承于QMainWindow...
- 如何从0到1设计实现一门自己的脚本语言
-
作者:dong...
- 三年级语文上册 仿写句子 需要的直接下载打印吧
-
描写秋天的好句好段1.秋天来了,山野变成了美丽的图画。苹果露出红红的脸庞,梨树挂起金黄的灯笼,高粱举起了燃烧的火把。大雁在天空一会儿写“人”字,一会儿写“一”字。2.花园里,菊花争奇斗艳,红的似火,粉...
- C++|那些一看就很简洁、优雅、经典的小代码段
-
目录0等概率随机洗牌:1大小写转换2字符串复制...
- 二年级上册语文必考句子仿写,家长打印,孩子照着练
-
二年级上册语文必考句子仿写,家长打印,孩子照着练。具体如下:...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- wireshark怎么抓包 (75)
- qt sleep (64)
- cs1.6指令代码大全 (55)
- factory-method (60)
- sqlite3_bind_blob (52)
- hibernate update (63)
- c++ base64 (70)
- nc 命令 (52)
- wm_close (51)
- epollin (51)
- sqlca.sqlcode (57)
- lua ipairs (60)
- tv_usec (64)
- 命令行进入文件夹 (53)
- postgresql array (57)
- statfs函数 (57)
- .project文件 (54)
- lua require (56)
- for_each (67)
- c#工厂模式 (57)
- wxsqlite3 (66)
- dmesg -c (58)
- fopen参数 (53)
- tar -zxvf -c (55)
- 速递查询 (52)