Tonado与Django的比较

本文探讨了Django与Tornado这两个Python Web框架的特点。Django以其自动化后台管理和丰富的组件适用于快速开发中小型网站,而Tornado则凭借其异步IO和高性能特性更适合处理高并发请求。两者各有优势与局限。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考链接:
http://www.maiziedu.com/article/9990/
https://www.oschina.net/code/snippet_77175_5421


tornado和django的开发思维完全不同。基本上整个tornado都是围绕着异步和协程的。代码中坑多,文档少。学习难度比django大不少。从django到tornado必须要转变编程思维。这点是需要注意的。Django是最出名的python框架,Google App Engine甚至Erlang都有框架受它影响。


django

优势:
一个大一统的框架,很多东西拿来就用,而且文档齐全。 什么都有,你能想到的功能其都有对应contrib组件给你用,大而全,适合小型的压力不大的项目,它最出名的是其全自动化的管理后台:只需要使用起ORM,做简单的对象定义,它就能自动生成数据库结构、以及全功能的管理后台。Django提供的方便,也意味着Django内置的ORM跟框架内的其他模块耦合程度高。应用程序必须使用Django内置的ORM,否则就不能享受到框架内提供的种种基于其ORM的便利;理论上可以切换掉其ORM模块,但这就相当于要把装修完毕的房子拆除重新装修,倒不如一开始就去毛胚房做全新的装修。Django的卖点是超高的开发效率,其性能扩展有限;采用Django的项目,在流量达到一定规模后,都需要对其进行重构,才能满足性能的要求。Django适用的是中小型的网站,或者是作为大型网站快速实现产品雏形的工具。Ruby的Rails也有类似的问题;以Twitter为例,推特到了今日的规模,不要说Rails,甚至是连Ruby都需要抛弃重来。

劣势:
一旦压力上来其是扛不住的,毕竟一是太重,而是非异步。


tornado

优势:
epoll异步性能高,还支持长连接。异步io,框架轻巧,适合组合各种模块来搭建服务。灵活性比较强。 Tornado走的是少而精的方向,它也有提供模板功能;虽然不鼓励,但作者是可以允许在模板进行少量编码的。 如果跟asp.net相比,Tornado有点类似仅实现了AsyncHttpHandler;除此之外,全部需要自己去实现。好吧,其实它有模板,有国际化支持,甚至还有内置的OAuth/OpenID模块,方便做第三方登录,它其实也直接实现了Http服务器。
劣势:
功能/第三方库相对少,而且想多实例还要自己去配置,再者没有很成熟的配套framework,而只是提供了核心的功能,其余的都需要你自己来做。 建议先熟悉django,随后在了解reactor基础上再来接触tornado. 这样你就可以在tornado中使用很多django成熟的东西,比如middleware。但它没有ORM(仅有一个mysql的超简单封装),甚至没有Session支持,更不要说Django那样自动化的后台。 假设是一个大型网站,在高性能的要求下,框架的各个部分往往都需要定制,可以复用的模块非常少;一个以Django开发的网站,各部分经过不断的定制,Django框架剩下的,很有可能也就是tornado一开始所能提供的这部分。


Http服务器

Tornado为了高效实现Comet/后端异步调用HTTP接口,是直接内嵌了HTTP服务器。 前端无需加apache / lighttpd / nginx等也可以供浏览器访问;但它并没有完整实现HTTP 1.1的协议,所以官方文档是推荐用户在生产环境下在前端使用nginx,后端反向代理到多个Tornado实例。 Tornado本身是单线程的异步网络程序,它默认启动时,会根据CPU数量运行多个实例;充分利用CPU多核的优势。


单线程异步

网站基本都会有数据库操作,而Tornado是单线程的,这意味着如果数据库查询返回过慢,整个服务器响应会被堵塞。 数据库查询,实质上也是远程的网络调用;理想情况下,是将这些操作也封装成为异步的;但Tornado对此并没有提供任何支持。 这是Tornado的设计,而不是缺陷。 一个系统,要满足高流量;是必须解决数据库查询速度问题的!数据库若存在查询性能问题,整个系统无论如何优化,数据库都会是瓶颈,拖慢整个系统!
异步并不能从本质上提到系统的性能;它仅仅是避免多余的网络响应等待,以及切换线程的CPU耗费。 如果数据库查询响应太慢,需要解决的是数据库的性能问题;而不是调用数据库的前端Web应用。对于实时返回的数据查询,理想情况下需要确保所有数据都在内存中,数据库硬盘IO应该为0;这样的查询才能足够快;而如果数据库查询足够快,那么前端web应用也就无将数据查询封装为异步的必要。 就算是使用协程,异步程序对于同步程序始终还是会提高复杂性;需要衡量的是处理这些额外复杂性是否值得。如果后端有查询实在是太慢,无法绕过,Tornaod的建议是将这些查询在后端封装独立封装成为HTTP接口,然后使用Tornado内置的异步HTTP客户端进行调用。

### Tornado 中实现类似 Django 的分层路由设计 Tornado 虽然不像 Django 那样内置了强大的 URL 分层机制,但可以通过自定义的方式实现类似的分层路由功能。以下是具体的设计思路和实现方法。 #### 自定义分层路由的逻辑 为了模拟 Django 的分层路由结构,可以将不同的子模块(如 `home`、`admin` 等)分别放置在独立的 Python 文件中,并通过统一的加载器动态导入这些模块中的路由规则[^1]。这种方式不仅提高了项目的可维护性,还便于扩展新的功能模块。 #### 示例代码:基于模块化的分层路由设计 假设项目中有两个主要的功能模块:`home` 和 `blog`,下面是如何实现它们的分层路由: ##### 1. 创建模块化路由文件 创建两个文件用于存储不同模块的路由规则: - `routes/home.py` ```python from handlers.home import IndexHandler, AboutHandler urlpatterns = [ (r"/", IndexHandler), (r"/about", AboutHandler) ] ``` - `routes/blog.py` ```python from handlers.blog import PostListHandler, PostDetailHandler urlpatterns = [ (r"/posts", PostListHandler), (r"/post/(?P<slug>[\w\-]+)", PostDetailHandler) ] ``` ##### 2. 定义通用的路由加载函数 编写一个工具函数来自动加载各个模块的路由规则并注册到应用实例中: ```python def load_routes(app): """ 动态加载所有模块的路由规则 :param app: Tornado 应用实例 """ routes_config = [ {"module": "routes.home", "prefix": r""}, {"module": "routes.blog", "prefix": r"/blog"} ] for config in routes_config: module_name = config["module"] prefix = config.get("prefix", "") try: # 导入指定模块 mod = __import__(module_name, fromlist=["urlpatterns"]) urlpatterns = getattr(mod, "urlpatterns", []) # 添加前缀路径 prefixed_patterns = [(f"{prefix}{pattern[0]}", *pattern[1:]) for pattern in urlpatterns] app.add_handlers(r".*", prefixed_patterns) except ImportError as e: raise Exception(f"Failed to load routes from {module_name}: {e}") ``` ##### 3. 主程序集成 在主入口文件中调用该加载函数完成最终的应用初始化工作: ```python import tornado.ioloop import tornado.web from settings import settings class Application(tornado.web.Application): def __init__(self): super().__init__() self.load_settings() def load_settings(self): """加载设置""" pass if __name__ == "__main__": app = Application() # 加载所有模块的路由 from utils.route_loader import load_routes load_routes(app) app.listen(8888, **settings) print("Server started on port 8888...") tornado.ioloop.IOLoop.current().start() ``` 以上实现了类似于 Django 的分层路由管理方案,其中每个业务模块都可以拥有自己独立的路由配置文件[^2]。 --- ### 总结 通过上述方法可以在 Tornado 框架下构建清晰合理的目录层次以及灵活易扩展的路由体系结构。此做法既保留了原生 API 的简洁高效特点又兼顾到了大型复杂系统的实际需求场景下的灵活性可读性[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值