千家信息网

Python中如何使用Tornado

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章给大家分享的是有关Python中如何使用Tornado的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。Tornado 基本操作Hello World经典的 hello
千家信息网最后更新 2026年11月02日Python中如何使用Tornado

这篇文章给大家分享的是有关Python中如何使用Tornado的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

Tornado 基本操作

Hello World

经典的 hello world 示例:

import tornado.web# 视图class MainHandler(tornado.web.RequestHandler):    def get(self):        self.write("Hello World.")# 路由application = tornado.web.Application([    (r"/", MainHandler),    (r"/hello", MainHandler),])if __name__ == '__main__':    import tornado.ioloop    application.listen(8000)    tornado.ioloop.IOLoop.instance().start()

整个过程其实就是在创建一个socket服务端并监听8000端口。当请求到来时,根据请求中的url和请求方式(post、get或put等)来指定相应的类中的方法来处理本次请求。在上述示例中 url 在路由系统匹配到时,则服务器会给浏览器返回 Hello World ,否则返回 404: Not Found(tornado内部定义的值), 即完成一次http请求和响应。

模板引擎

Tornao中的模板语言和django中类似。模板引擎将模板文件载入内存,然后将数据嵌入其中,最终获取到一个完整的字符串,再将字符串返回给请求者。
不过还是有区别的。Tornado 的模板支持"控制语句"和"表达语句",控制语句是使用 {% 和 %} 包起来的。例如 {% if len(items) > 2 %}。表达语句是使用 {{ 和 }} 包起来的,例如 {{ items[0] }} 。
控制语句和对应的 Python 语句的格式基本完全相同。支持 if、for、while 和 try,这些语句逻辑结束的位置需要用 {% end %} 做标记。还通过 extends 和 block 语句实现了模板继承。这些在 template 模块的代码文档中有着详细的描述。在使用模板前需要在setting中设置模板路径:"template_path" : "tpl"
使用模板引擎的简单示例,后端代码:

import tornado.webclass IndexHandler(tornado.web.RequestHandler):    def get(self):        self.render("index.html", k1='v1', k2='v2')  # k1和k2是传给模板引擎处理的内容application = tornado.web.Application([    (r"/index", IndexHandler),])if __name__ == '__main__':    import tornado.ioloop    application.listen(8000)    tornado.ioloop.IOLoop.instance().start()

前端代码,模板语言的使用:

Hello World

{{ k1 }}

{% if k2 == 'v2' %}

k2 == v2

{% else %}}

k2 != v2

{% end %}

加载配置

上面的前端代码,最好是统一保存在某个目录里,比如新建个tpl目录来存放。把html文件移过去之后,现在render()方法就找不到这个文件了。当然可以改一下参数,把目录名加进去。不过推荐的做法是把tpl目录加到配置里去,对上面的代码进去修改,加入配置信息:

class IndexHandler(tornado.web.RequestHandler):    def get(self):        self.render("index.html", k1='v1', k2='v2')# 配置就是个key-value的字段settings = {    'template_path': 'tpl'}application = tornado.web.Application([    (r"/index", IndexHandler),], **settings)  # application加载配置信息

POST

先准备好如下的页面,在输入框里填入要搜索的关键字,提交后就跳转到搜索引擎搜索的结果:

后端的代码:

import tornado.webclass SearchHandler(tornado.web.RequestHandler):    def get(self):        self.render("baidu.html")    def post(self):        wd = self.get_argument('wd')        print(wd)        self.redirect('https://www.baidu.com/s?wd=%s' % wd)settings = {    'template_path': 'tpl'}application = tornado.web.Application([    (r"/baidu", SearchHandler),], **settings)if __name__ == '__main__':    import tornado.ioloop    application.listen(8000)    tornado.ioloop.IOLoop.instance().start()

上面的示例,post请求最后是用redirect()返回的,这个是页面的跳转。
获取提交的参数的方法有这些:

class LoginHandler(tornado.web.RequestHandler):    def post(self):        # 获取URL中以GET形式传递的数据        self.get_query_argument()        self.get_query_arguments()        # 获取请求体中以POST形式传递的数据        self.get_body_argument()        self.get_body_arguments()        # 从上面2个里都尝试获取        self.get_argument()        self.get_arguments()

静态文件(图片)

静态文件是给用户直接下载的,所以应该单独存放,并且在配置里注册对应的目录。配置的写法:

settings = {    'template_path': 'tpl',  # 模板    'static_path': 'imgs',  # 静态文件}

现在可以根据配置里的名称去创建一个新的文件夹 static 用来存放静态文件。然后放张图片进去。
这里故意不用static作为静态文件文件夹的名称,这里只是注册文件夹,但是前端引用的时候,无论你的静态文件放在那里,都是用 static/文件名称 。
加一个img标签到html里,然后验证一下效果。注意src里用的是static,而不是文件夹真正的名称:

这里前端引用的是必须用static,不过这个名字也是可以自定义的:

settings = {    'template_path': 'tpl',  # 模板    'static_path': 'imgs',  # 静态文件    'static_url_prefix': '/statics/',  # 注意两边都要有斜杠/}

其他操作

self.request.cookies : 获取cookies
self.set_cookie() : 设置cookie
self.request.headers : 获取请求头
self.set_header() : 设置响应头,如果出现同一个响应头,会覆盖
self.add_header() : 设置响应头,如果出现同一个响应头,则追加

Tornado 没有提供 session ,所以要用的话,得另外写。同样的,缓存也没有。

进阶操作

最基本的就是上面那些了,这里再补充一点别的。

自定义UIMethod以及UIModule

这个就是模板引擎里的自定义函数。
UIMethod 自定义的是个函数,UIModule 自定义的是个类。

定义
把自定义的函数和自定义的类单独写在文件里:

# ui_methods.pydef test1(self):  # 这里的self不能去掉    return "TEST1"def test2(self):    return "TEST2"# ui_module.pyfrom tornado.web import UIModulefrom tornado import escapeclass Test(UIModule):    def render(self, *args, **kwargs):        return escape.xhtml_escape('

UI Module TEST

')

注册
写一个完整的服务,这里加上注册的代码。先导入上面的文件,然后分别在settings里注册:

import tornado.webimport ui_methods as mtimport ui_modules as mdclass MainHandler(tornado.web.RequestHandler):    def get(self):        self.render('ui.html')settings = {    'template_path': 'tpl',  # 模板    'static_path': 'static',  # 静态文件,这里不重要    'static_url_prefix': '/statics/',  # 注意两边都要有斜杠/    'ui_methods': mt,    'ui_modules': md,}application = tornado.web.Application([    (r"/ui", MainHandler),], **settings)if __name__ == '__main__':    import tornado.ioloop    application.listen(8000)    tornado.ioloop.IOLoop.instance().start()

使用
这里只需要看明白前端调用的方法就可以了

UI Method

{{ test1() }}

{{ test2() }}

UI Module

{% module Test() %}

UIModule里的方法
render 方法返回的内容就是调用模板的位置显示的内容:

class Test(UIModule):    def javascript_files(self):        pass    def embedded_javascript(self):        pass    def css_files(self):        pass    def embedded_css(self):        pass    def render(self, *args, **kwargs):        return escape.xhtml_escape('

UI Module TEST

')

javascript的方法会在body的尾部插入script标签,插入js代码
css的方法则会在head里插入style标签,设置css
files就是直接引入文件,进行设置
embedded就是插入返回的字符串作为设置

CSRF

首先在settings里启用csrf:

settings = {    "xsrf_cookies": True,}

在 form 中使用

{% raw xsrf_form_html() %}

{{ xsrf_form_html() }} 能够输出完整的input标签,但是直接用回被解析为字符串,带着标签的信息作为字符串显示出来。所以上面用的是 {% raw xsrf_form_html() %} 。

在 Ajax 中使用
Ajax使用时,本质上就是去获取本地的cookie,携带cookie再来发送请求:

function getCookie(name) {    var r = [xss_clean].match("\\b" + name + "=([^;]*)\\b");    return r ? r[1] : undefined;}jQuery.postJSON = function(url, args, callback) {    args._xsrf = getCookie("_xsrf");    $.ajax({url: url, data: $.param(args), dataType: "text", type: "POST",        success: function(response) {        callback(eval("(" + response + ")"));    }});};

上传文件

先准备一个form表单上传文件的html页面:

        上传文件    

接收上传文件:

import tornado.webclass MainHandler(tornado.web.RequestHandler):    def get(self):        self.render('index.html')    def post(self, *args, **kwargs):        file_metas = self.request.files["fff"]        # print(file_metas)        for meta in file_metas:            file_name = meta['filename']            with open(file_name,'wb') as up:                up.write(meta['body'])settings = {    'template_path': 'template',}application = tornado.web.Application([    (r"/index", MainHandler),], **settings)if __name__ == '__main__':    import tornado.ioloop    application.listen(8000)    tornado.ioloop.IOLoop.instance().start()

上传文件还可以用Ajax,另外还有借助iframe标签实现的伪Ajax的实现,略...

异步非阻塞

异步非阻塞IO,高并发高性能是tornado的特点,所以这小节很重要。但是具体内容也没搞明白,只能尽量先记一些。
首先要引入下面的2个模块:

from tornado import genfrom tornado.concurrent import Futureclass AsyncHandler(tornado.web.RequestHandler):    @gen.coroutine    def get(self):        future = Future()        future.add_done_callback(self.doing)        yield future    def doing(self,*args, **kwargs):        self.write('async')        self.finish()

当发送GET请求时,由于方法被@gen.coroutine装饰且yield 一个Future对象,那么Tornado会等待,等待用户向future对象中放置数据或者发送信号,如果获取到数据或信号之后,就开始执行doing方法。
这里发送请求后,永远也不会返回,就是按上面说的Tornado一直在等待。等待调用了 future.set_result(result) 这个方法。之后就会调用回调函数,而set_result方法里传递进去的参数,可以通过 future.result() 获取到。大致就是这么的用法,但是没有个使用示例有点不好理解。

Future类
Future类位于tornado源码的concurrent模块中。下面是Future类里的一部分代码作为分析之用:

class Future(object):    def done(self):        return self._done    def result(self, timeout=None):        self._clear_tb_log()        if self._result is not None:            return self._result        if self._exc_info is not None:            raise_exc_info(self._exc_info)        self._check_done()        return self._result    def add_done_callback(self, fn):        if self._done:            fn(self)        else:            self._callbacks.append(fn)    def set_result(self, result):        self._result = result        self._set_done()    def _set_done(self):        self._done = True        for cb in self._callbacks:            try:                cb(self)            except Exception:                app_log.exception('exception calling callback %r for %r',                                  cb, self)        self._callbacks = None

Future类重要成员函数:

  • def done(self) : Future的_result成员是否被设置

  • def result(self, timeout=None) : 获取Future对象的结果

  • def add_done_callback(self, fn) : 添加一个回调函数fn给Future对象。如果这个Future对象已经done,则直接执行fn,否则将fn加入到Future类的一个成员列表中保存。

  • def_set_done(self) : 一个内部函数,主要是遍历列表,逐个调用列表中的callback函数,也就是前面 add_done_calback 加如来的。

  • def set_result(self, result) : 给Future对象设置result,并且调用_set_done。也就是说,当Future对象获得result后,所有add_done_callback加入的回调函数就会执行。

这里最终就是希望 future 调用 set_result ,然后就是执行回调函数。

自定义异步非阻塞Web框架

这节主要是想以源码的方式展示分析tornado是怎么实现异步非阻塞的。代码应该不是超的源码,只是借鉴了思路,做了很多简化。
下面是实现异步非阻塞的代码,主要是 select+socket :
https://www.cnblogs.com/wupeiqi/p/6536518.html

什么场景考虑使用Tornado

复杂的应用还是用django来开发。
如果要开发一个API的功能,或者其他的简单的工具、应用,也不用操作数据库。就可以用tornado或者是其他简单的框架。就不需要用django了。
可以选择的简单的框架还有Flask。

感谢各位的阅读!关于"Python中如何使用Tornado"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

文件 模板 就是 方法 代码 函数 语句 静态 配置 对象 内容 引擎 数据 前端 字符 字符串 标签 目录 示例 面的 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 苏州找大状互联网科技有限公司 互联网和科技创新 金融科技与互联网金融 嘟嘟瓜互联网科技 成都仁贤领冠互联网科技有限公司 互联网巨头投资的硬核科技 湖南洣水互联网科技有限公司扣款 玖二柒互联网科技公司待遇 华服互联网科技官网 米聚互联网科技南京有限公司排面 中科明德北京互联网科技 小米互联网科技园入驻 领航科技大厦互联网公司 互联网科技数字货币 湖北辰鑫科技互联网 科技互联网经济论坛 数字科技和互联网金融哪个好 上海互联网科技园景观 重庆科技产业互联网有哪些 小牛互联网科技有限公司地址 北京互联网络科技有限公司 广州善班互联网科技 开启互联网科技时代小说 茂名市互联网科技产业园 互联网时代科技改变生活 彤创互联网科技有限公司 河南住房之家互联网科技 互联网金融运营模式中的金融科技 互联网科技品牌 盐城市攀科互联网科技有限公司
0