python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python Tornado 框架入门

Python Tornado 框架从零搭建你的第一个异步 Web 应用(最新推荐)

作者:李高钢

Tornado是一款基于异步非阻塞架构的 Python Web 框架,擅长处理长连接与高并发场景,其核心优势在于原生支持WebSocket、自带高性能服务器,本文给大家介绍Python Tornado框架从零搭建你的第一个异步 Web应用,感兴趣的朋友跟随小编一起看看吧

前言

前面几篇文章我们依次介绍了 Flask、Django、FastAPI 这三大 Python Web 框架,今天来聊聊一位"资历更老"但依然活跃在长连接、高并发场景中的选手——Tornado。

Tornado 由 FriendFeed 公司开发,2009 年被 Facebook 收购后开源,最早就是为了解决 FriendFeed 网站"实时信息流"场景下大量长连接、高并发的性能问题而生的。它的核心关键词是**“异步非阻塞”**——早在 Python 3 原生 asyncio 出现之前(Python 3.4+),Tornado 就已经用自己的一套事件循环机制实现了异步 I/O,是 Python 异步 Web 开发的"老前辈"。

时至今日,虽然 FastAPI 等基于原生 asyncio 的新框架风头正劲,但 Tornado 凭借其成熟稳定的异步网络库、内置 WebSocket 支持,依然广泛应用于长轮询、实时推送、聊天室、监控系统等需要维持大量并发连接的场景。

本文将带你了解 Tornado 的核心概念,并通过两个例子——一个基础 Web 接口,一个 WebSocket 实时通信——体验一下 Tornado 在处理长连接场景时的独特优势。

一、Tornado 是什么?

Tornado 全称 “Tornado Web Server”,它既是一个 Web 框架,也是一个异步网络库,可以说是"框架 + 服务器"二合一。

Tornado 的主要特点

和前面几个框架的定位差异

维度FlaskDjangoFastAPITornado
核心定位微框架全功能框架现代高性能 API 框架异步网络库 + Web 框架
并发模型同步(默认)同步为主原生异步(ASGI)原生异步(自有事件循环,兼容 asyncio)
WebSocket需借助扩展需借助 Channels 等扩展支持,但非核心卖点原生内置,核心优势之一
是否自带生产级服务器否否否是
典型场景小型项目、原型中大型完整系统API 服务、微服务长连接、实时推送、聊天室

可以看到,Tornado 并不是要跟 FastAPI 拼"谁的 API 开发体验更好",而是在"需要同时维持海量并发连接"这个细分场景里有着天然优势。

二、环境准备

按惯例,先创建虚拟环境:

# 创建虚拟环境
python -m venv venv
# 激活虚拟环境
# Windows:
venv\Scripts\activate
# macOS / Linux:
source venv/bin/activate

安装 Tornado:

pip install tornado

查看版本确认安装成功:

python -c "import tornado; print(tornado.version)"

三、动手实践一:最基础的 Web 服务

新建 app.py:

import tornado.ioloop
import tornado.web
class HelloHandler(tornado.web.RequestHandler):
    """处理 GET / 请求的处理器"""
    def get(self):
        self.write({"message": "Hello, Tornado!"})
class GreetHandler(tornado.web.RequestHandler):
    """演示路径参数与查询参数的处理器"""
    def get(self, name):
        # 通过 self.get_query_argument 获取 URL 查询参数,可设置默认值
        lang = self.get_query_argument("lang", default="zh")
        greeting = "你好" if lang == "zh" else "Hello"
        self.write({"greeting": f"{greeting}, {name}!"})
def make_app():
    return tornado.web.Application([
        (r"/", HelloHandler),
        (r"/greet/([^/]+)", GreetHandler),   # 用正则捕获路径参数
    ])
if __name__ == "__main__":
    app = make_app()
    app.listen(8888)
    print("Tornado 服务已启动: http://127.0.0.1:8888")
    tornado.ioloop.IOLoop.current().start()

运行:

python app.py

打开浏览器依次访问:

代码要点解析

四、动手实践二:一个简单的 WebSocket 实时聊天室

这才是 Tornado 真正大放异彩的场景。下面用不到 40 行代码实现一个"多人广播聊天室":谁发一条消息,所有在线的人都能实时收到。

chat_server.py:

import tornado.ioloop
import tornado.web
import tornado.websocket
# 保存所有已连接的客户端
clients = set()
class ChatWebSocket(tornado.websocket.WebSocketHandler):
    def check_origin(self, origin):
        # 简单起见,允许所有来源的跨域连接(生产环境请按需收紧)
        return True
    def open(self):
        """客户端建立连接时触发"""
        clients.add(self)
        print(f"新用户连接,当前在线人数:{len(clients)}")
    def on_message(self, message):
        """收到某个客户端发来的消息时触发,广播给所有在线用户"""
        for client in clients:
            client.write_message(f"用户说: {message}")
    def on_close(self):
        """客户端断开连接时触发"""
        clients.discard(self)
        print(f"用户断开,当前在线人数:{len(clients)}")
class IndexHandler(tornado.web.RequestHandler):
    """提供一个简单的聊天页面,方便直接在浏览器里测试"""
    def get(self):
        self.write("""
        <!DOCTYPE html>
        <html><head><meta charset="utf-8"><title>Tornado 聊天室</title></head>
        <body>
            <input id="msg" placeholder="输入消息,回车发送">
            <ul id="log"></ul>
            <script>
                const ws = new WebSocket("ws://" + location.host + "/ws");
                ws.onmessage = (e) => {
                    const li = document.createElement("li");
                    li.textContent = e.data;
                    document.getElementById("log").appendChild(li);
                };
                document.getElementById("msg").addEventListener("keydown", (e) => {
                    if (e.key === "Enter" && e.target.value) {
                        ws.send(e.target.value);
                        e.target.value = "";
                    }
                });
            </script>
        </body></html>
        """)
def make_app():
    return tornado.web.Application([
        (r"/", IndexHandler),
        (r"/ws", ChatWebSocket),
    ])
if __name__ == "__main__":
    app = make_app()
    app.listen(8888)
    print("聊天室已启动: http://127.0.0.1:8888")
    tornado.ioloop.IOLoop.current().start()

运行后,用两个不同的浏览器标签页打开 http://127.0.0.1:8888,在任意一个页面的输入框里发消息回车,会发现所有打开的页面都能实时收到这条广播消息——这就是 WebSocket 双向实时通信的效果,也是 Tornado 相比 Flask/Django 在这类场景下最直观的优势体现。

代码要点解析

五、常用生态一览

库/工具用途
tornado.websocket内置 WebSocket 支持
tornado.gen / asyncio编写异步协程逻辑
motorMongoDB 的异步驱动,与 Tornado 搭配常见
aiomysql / asyncpgMySQL / PostgreSQL 的异步驱动
Redis Pub/Sub多进程/多机场景下同步 WebSocket 广播消息
Supervisor / systemd生产环境进程守护,配合多进程部署(Tornado 自带服务器,无需额外的 WSGI/ASGI 网关)

六、总结

通过本文,我们了解了:

  1. Tornado 是一个"异步网络库 + Web 框架"二合一的选手,早在 Python 原生 asyncio 之前就已经用自己的事件循环实现了异步非阻塞架构;
  2. 它用面向对象的 RequestHandler 子类来组织路由逻辑,正则表达式定义 URL 规则,风格上比 Flask/FastAPI 略"重"一些;
  3. Tornado 自带生产级 HTTP 服务器,不需要额外配置 Gunicorn/Uvicorn 等网关;
  4. 原生 WebSocket 支持是 Tornado 最具辨识度的能力,几十行代码就能搭建一个实时广播聊天室,这在需要维持海量长连接的场景(消息推送、实时监控、在线协作)中非常有优势。

至此,Flask、Django、FastAPI、Tornado 四个 Python Web 框架都已经介绍完毕。简单总结一下各自的"最佳应用场景":

没有"最好"的框架,只有"最适合当前场景"的框架,希望这个系列能帮你在做技术选型时多一份判断依据。

参考资料

到此这篇关于Python Tornado 框架从零搭建你的第一个异步 Web 应用(最新推荐)的文章就介绍到这了,更多相关Python Tornado 框架入门内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文