tornado入门笔记

隔壁老王
• 阅读 2107

官方文档

https://www.tornadoweb.org/en/stable/

简单使用

# !/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: Wjy
import tornado.ioloop  # 启动
import tornado.web  # 请求对象
import tornado.template  # 模板


class Index(tornado.web.RequestHandler):
    def get(self, *args, **kwargs):
        self.write("首页123")


def make_app():
    return tornado.web.Application([
        (r"/index", Index)
    ])  # debug=True会自动加载改变的py文件,不过会导致自动挂载后台


if __name__ == '__main__':
    app = make_app()
    app.listen(8000)
    tornado.ioloop.IOLoop.current().start()

单进程

# -*- coding: utf-8 -*-
# Author: Wjy
import tornado.ioloop  # 启动
import tornado.web  # 请求对象
import tornado.template  # 模板
import tornado.autoreload
import tornado.netutil
import tornado.process
from tornado.httpserver import HTTPServer


class Index(tornado.web.RequestHandler):
    def get(self, *args, **kwargs):
        self.write("首页123")


if __name__ == '__main__':
    tornado.autoreload = True  # debug模式
    app = tornado.web.Application([
            (r"/index", Index)
        ])  # debug=True会自动加载改变的py文件,不过会导致自动挂载后台
    http = tornado.httpserver.HTTPServer(app)
    http.listen(8000)
    tornado.ioloop.IOLoop.current().start()

多进程

# !/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: Wjy
import tornado.ioloop  # 启动
import tornado.web  # 请求对象
import tornado.template  # 模板
import tornado.httpserver


class MainHandler(tornado.web.RequestHandler):
    def get(self, *args, **kwargs):
        # 获取get请求一个参数
        print(self.get_argument("a"))
        # 获取get请求中参数列表
        print(self.get_arguments("b"))
        self.write("get 请求")

    def post(self, *args, **kwargs):
        # 获取表单数据
        # print(self.get_body_argument("name"))
        # 获取表单列表数据
        # print(self.get_body_arguments("body"))
        # 获取body原始数据
        print(self.request.body)
        # 获取请求头
        print(self.request.headers)
        self.write("post 请求")

    def head(self, *args, **kwargs):
        self.write("head 请求")

    def delete(self, *args, **kwargs):
        self.write("delete 请求")

    def patch(self, *args, **kwargs):
        self.write("patch 请求")

    def put(self, *args, **kwargs):
        self.write("put 请求")

    def options(self, *args, **kwargs):
        self.write("options 请求")


    def prepare(self):
        '''
        前置钩子
        :return:
        '''
        # self.write("prepare 前置钩子")

    def on_finish(self):
        '''
        后置钩子
        :return:
        '''
        # self.write("on_finish 后置钩子")

    def initialize(self):
        '''
        钩子
        :return:
        '''
        # self.write("initialize 每次都会被调用的钩子")


class Index(tornado.web.RequestHandler):
    def get(self, *args, **kwargs):
        self.write("首页123")


if __name__ == '__main__':
    make_app = tornado.web.Application([
        (r"/", MainHandler),
        (r"/index", Index)
    ])
    app = tornado.httpserver.HTTPServer(make_app)  # 标准写法
    app.bind(8000)
    app.start(1)  # 多进程控制
    tornado.ioloop.IOLoop.current().start()

说明:

http_server.bind(port)方法是将服务器绑定到指定端口。

http_server.start(num_processes=1)方法指定开启几个进程,参数num_processes默认值为1,即默认仅开启一个进程;如果num_processes为None或者<=0,则自动根据机器硬件的cpu核芯数创建同等数目的子进程;如果num_processes>0,则创建num_processes个子进程。

1.关于app.listen()

app.listen()这个方法只能在单进程模式中使用。

对于app.listen()与手动创建HTTPServer实例

http_server = tornado.httpserver.HTTPServer(app) 
http_server.listen(8000)

2.关于多进程

虽然tornado给我们提供了一次开启多个进程的方法,但是由于:

  • 每个子进程都会从父进程中复制一份IOLoop实例,如过在创建子进程前我们的代码动了IOLoop实例,那么会影响到每一个子进程,势必会干扰到子进程IOLoop的工作;

  • 所有进程是由一个命令一次开启的,也就无法做到在不停服务的情况下更新代码;

  • 所有进程共享同一个端口,想要分别单独监控每一个进程就很困难。

不建议使用这种多进程的方式,而是手动开启多个进程,并且绑定不同的端口。

Application中settings可以设置的参数

#设置templates路径:
template_path = os.path.join(os.path.dirname(__file__), "templates")

#设置静态文件解析路径:
static_path = os.path.join(os.path.dirname(__file__), "static"),

#设置防跨站请求攻击:
xsrf_cookies = True,
# {% module xsrf_form_html() %} html中加入该参数
#默认为False,即不可防御。

#设置登陆路径,未登陆用户在操作时跳转会用到这个参数:
login_url = "/login-do",
#默认为@tornado.web.authenticated

#设置调试模式:
debug = True,
#默认为False,即不是调试模式。

#设置cookie密钥:
cookie_secret = "dskfhisdjklagkfdklag;lkjasdklgjkldsjaklgjkldsfksdklf"
#默认为字符串"secure cookies"

#设置是否自动编码:在2.0以上需要设置此项来兼容您之前的APP
autoescape = None,
#不设置默认为自动编码。

#设置template_loader,可以从独立的路径中导入template:
template_loader=utils.ZipLoader,
#其中utils为自己定义的模块,ZipLoader是tornado.template.BaseLoader的子类。

#设置gzip压缩:
gzip=True

#设置静态路径头部:
static_url_prefix = "/mystatic/",
#默认是"/static/"

#设置静态文件处理类:
static_handler_class = MyStaticFileHandler,
#默认是tornado.web.StaticFileHandler

#设置静态文件的参数:
static_handler_args = { "key1":"value1", "key2":"value2"  }
#默认为空字典。

#设置日志处理函数
log_function = your_fun,
# 日志处理函数your_fun,按照自己的意图记录日志。

define和options

# !/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: Wjy
import tornado.ioloop  # 启动
import tornado.web  # 请求对象
import tornado.httpserver
from tornado.options import options, define

# 定义全局变量,options.出定义的这个变量
define("port", default=8000, help="监听的端口")


class Index(tornado.web.RequestHandler):
    def get(self, *args, **kwargs):
        self.write("首页123")


if __name__ == '__main__':
    tornado.autoreload = True  # debug模式
    app = tornado.web.Application([
        (r"/index", Index)
    ])
    http = tornado.httpserver.HTTPServer(app)
    http.listen(options.port)
    tornado.ioloop.IOLoop.current().start()

模板基础

# !/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: Wjy
import tornado.ioloop  # 启动
import tornado.web  # 请求对象
import tornado.httpserver  # http服务
import tornado.template  # 模板的使用
import tornado.autoreload
from tornado.options import options, define

# 定义全局变量,options.出定义的这个变量
define("port", default=8000, help="监听的端口")


class Index(tornado.web.RequestHandler):
    def get(self, *args, **kwargs):
        # 构建模板
        t = tornado.template.Template("<html>{{ myvalue }}</html>")
        # 填充模板参数
        self.write(t.generate(myvalue="hello1"))


if __name__ == '__main__':

    app = tornado.web.Application([
        (r"/index", Index)
    ])
    http = tornado.httpserver.HTTPServer(app)
    http.listen(options.port)

    instance = tornado.ioloop.IOLoop.instance().start()

模板语法参考

模板表达式由双花括号包围:。内容可以是任何python表达式,它将根据当前的autoescape设置进行转义并插入到输出中。其他模板指令使用。{{ ... }}{% %}

要注释掉一个部分,使其从输出中省略,请用它包围。{# ... #}

这些标签可以被转义为{{!,{%!以及{#! 如果需要包括文字{{,{%或{#在输出中。

{% apply *function* %}...{% end %}
将函数应用于apply 和之间的所有模板代码的输出end:

{% apply linkify %}{{name}} said: {{message}}{% end %}
请注意,作为实现细节,应用块实现为嵌套函数,因此可能与通过设置的变量或使用或 在循环内进行奇怪的交互。{% set %}{% break %}{% continue %}

{% autoescape *function* %}
设置当前文件的自动调用模式。这不会影响其他文件,甚至是那些引用的文件。请注意,也可以在 或者全局配置自动加载:{% include %}ApplicationLoader

{% autoescape xhtml_escape %}
{% autoescape None %}
{% block *name* %}...{% end %}
表示用于的可命名的可替换块。父模板中的块将替换为子模板中同名块的内容:{% extends %}
<!-- base.html -->
<title>{% block title %}Default title{% end %}</title>

<!-- mypage.html -->
{% extends "base.html" %}
{% block title %}My page title{% end %}
{% comment ... %}
将从模板输出中删除的注释。请注意,没有标签; 评论从单词 到结束标记。{% end %}comment%}
{% extends *filename* %}
从另一个模板继承。使用的模板extends应包含一个或多个block标记,以替换父模板中的内容。子block 标记中未包含在标记中的任何内容都将被忽略。有关示例,请参阅标记。{% block %}
{% for *var* in *expr* %}...{% end %}
与python for语句相同。 并且 可以在循环内使用。{% break %}{% continue %}
{% from *x* import *y* %}
与python import语句相同。
{% if *condition* %}...{% elif *condition* %}...{% else %}...{% end %}
条件语句 - 输出条件为真的第一部分。(这些elif和else部分是可选的)
{% import *module* %}
与python import语句相同。
{% include *filename* %}
包含另一个模板文件。包含的文件可以看到所有局部变量,就好像它被直接复制到include 指令点(该指令是一个例外)。或者,可以用于包括具有隔离命名空间的另一个模板。{% autoescape %}{% module Template(filename, **kwargs) %}
{% module *expr* %}
呈现一个UIModule。该输出UIModule未转义:

{% module Template("foo.html", arg=42) %}
UIModules是tornado.web.RequestHandler 类的一个特性(特别是它的render方法),当模板系统在其他环境中单独使用时,它将不起作用。

{% raw *expr* %}
输出给定表达式的结果而不进行自动转换。
{% set *x* = *y* %}
设置局部变量。
{% try %}...{% except %}...{% else %}...{% finally %}...{% end %}
与python try语句相同。
{% while *condition* %}... {% end %}
与python while语句相同。 并且 可以在循环内使用。{% break %}{% continue %}
{% whitespace *mode* %}
为当前文件的其余部分设置空白模式(或直到下一个指令)。请参阅 可用选项。Tornado 4.3中的新功能。{% whitespace %}filter_whitespace

类引用

class tornado.template.Template(template_string,name =“<string>”,loader = None,compress_whitespace = None,autoescape =“xhtml_escape”,whitespace = None )[source]
编译模板。

我们从给定的template_string编译成Python。您可以使用generate()从变量生成模板。

构造一个模板。

参数:

template_string(str) - 模板文件的内容。
name(str) - 加载模板的文件名(用于错误消息)。
loader(tornado.template.BaseLoader) - BaseLoader负责此模板,用于解析和指令。{% include %}{% extend %}
compress_whitespace(bool) - 自Tornado 4.3以来已弃用。相当于whitespace="single"if和 whitespace="all"false。
autoescape(str) - 模板命名空间中函数的名称,或None默认情况下禁用转义。
whitespace(str) - 指定空白处理的字符串; 看看filter_whitespace选项。
版本4.3更改:添加whitespace参数; 已弃用compress_whitespace。

generate(** kwargs )[来源]
使用给定的参数生成此模板。

class tornado.template.BaseLoader(autoescape ='xhtml_escape',namespace = None,whitespace = None )[来源]
模板加载器的基类。

您必须使用模板加载器来使用和等模板结构 。加载程序在第一次加载后缓存所有模板。{% extends %}{% include %}
构造模板加载器。

参数:

autoescape(str) - 模板命名空间中函数的名称,例如“xhtml_escape”,或None默认情况下禁用自动转义。
namespace(dict) - 要添加到默认模板名称空间的字典,或None。
whitespace(str) - 一个字符串,指定模板中空格的默认行为; 看看filter_whitespace选项。对于以“.html”和“.js”结尾的文件,默认为“single”,对于其他文件,默认为“all”。
版本4.3中已更改:已添加whitespace参数。

reset()[来源]
重置已编译模板的缓存。

resolve_path(name,parent_path = None )[来源]
将可能相对路径转换为绝对路径(在内部使用)。

load(name,parent_path = None )[来源]
加载模板。

class tornado.template.Loader(root_directory,** kwargs )[来源]
从单个根目录加载的模板加载器。

class tornado.template.DictLoader(dict,** kwargs )[来源]
从字典加载的模板加载器。

异常tornado.template.ParseError(消息,文件名=无,行号= 0 )[来源]
引发模板语法错误。

ParseError实例具有指示错误位置的属性filename和lineno属性。

版本4.3中已更改:已添加filename和lineno属性。

tornado.template.filter_whitespace(模式,文字)[来源]
text根据变换空格mode。

可用的模式是:

all:返回所有未经修改的空格。
single:使用单个空格字符折叠连续的空格,保留换行符。
oneline:将所有空白行都折叠到一个空格字符中,删除过程中的所有换行符。

模板应用py文件

# !/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: Wjy
import tornado.ioloop  # 启动
import tornado.web  # 请求对象
import tornado.httpserver  # http服务
import tornado.template  # 模板的使用
import tornado.autoreload
from tornado.options import options, define

# 定义全局变量,options.出定义的这个变量
define("port", default=8000, help="监听的端口")


class Index(tornado.web.RequestHandler):
    def get(self, *args, **kwargs):
        students = [dict(name='david'), dict(name='jack')]

        # 原始写法
        # loader = tornado.template.Loader("templates")
        # t = loader.load("base.html")
        # self.write(t.generate(students=students))

        self.render("test.html", students=students)


if __name__ == '__main__':

    app = tornado.web.Application([
        (r"/index", Index)
    ],
    template_path="./templates"  # 与render配合使用
    )
    http = tornado.httpserver.HTTPServer(app)
    http.listen(options.port)

    instance = tornado.ioloop.IOLoop.current().start()

base.html

<html>
  <head>
    <title>{% block title %}Default title{% end %}</title>
  </head>
  <body>
    <ul>
      {% for student in students %}
        {% block student %}
          <li>{{ escape(student['name']) }}</li>
        {% end %}
      {% end %}
    </ul>
  </body>
</html>

test.html

{% extends "base.html" %}

{% block title %}A bolder title{% end %}

{% block student %}
  <li><span style="bold">{{ escape(student['name']) }}</span></li>
{% end %}

路由的实现

tornado.routing- 基本路由实现

Tornado使用Router 类实现将HTTP请求路由到适当的处理程序。的tornado.web.Application类是一个 Router实现,并且可以直接使用,或在该模块中的类可以用于额外的灵活性。的RuleRouter 类可以匹配比多个准则Application,或Router 接口可以被继承为最大定制。

Router接口扩展HTTPServerConnectionDelegate 以提供额外的路由功能。这也意味着,任何 Router实现可以直接用作request_callback 用于HTTPServer构造函数。

Router子类必须实现一个find_handler方法来提供一个合适的HTTPMessageDelegate实例来处理请求:

class CustomRouter(Router):
    def find_handler(self, request, **kwargs):
        # some routing logic providing a suitable HTTPMessageDelegate instance
        return MessageDelegate(request.connection)

class MessageDelegate(HTTPMessageDelegate):
    def __init__(self, connection):
        self.connection = connection

    def finish(self):
        self.connection.write_headers(
            ResponseStartLine("HTTP/1.1", 200, "OK"),
            HTTPHeaders({"Content-Length": "2"}),
            b"OK")
        self.connection.finish()

router = CustomRouter()
server = HTTPServer(router)

实现的主要责任Router是提供从请求到HTTPMessageDelegate将处理此请求的实例的映射。在上面的示例中,我们可以看到即使没有实例化路由也可以进行路由Application。

为了路由到RequestHandler实现,我们需要一个 Application实例。get_handler_delegate 提供了一种HTTPMessageDelegate 为给定请求创建的便捷方式RequestHandler。

以下是我们如何RequestHandler通过HTTP方法路由到子类的简单示例 :

resources = {}

class GetResource(RequestHandler):
    def get(self, path):
        if path not in resources:
            raise HTTPError(404)

        self.finish(resources[path])

class PostResource(RequestHandler):
    def post(self, path):
        resources[path] = self.request.body

class HTTPMethodRouter(Router):
    def __init__(self, app):
        self.app = app

    def find_handler(self, request, **kwargs):
        handler = GetResource if request.method == "GET" else PostResource
        return self.app.get_handler_delegate(request, handler, path_args=[request.path])

router = HTTPMethodRouter(Application())
server = HTTPServer(router)

ReversibleRouterinterface添加了区分路由的功能,并使用路由名称和其他参数将它们反转到原始URL。Application本身就是一个ReversibleRouter类的实现。

RuleRouter并且ReversibleRuleRouter是Router和ReversibleRouter接口的实现, 并且可以用于创建基于规则的路由配置。

规则是Rule类的实例。它们包含a Matcher,它提供用于确定规则是否与特定请求和目标匹配的逻辑,可以是以下之一。

一个例子HTTPServerConnectionDelegate:

router = RuleRouter([
    Rule(PathMatches("/handler"), ConnectionDelegate()),
    # ... more rules
])

class ConnectionDelegate(HTTPServerConnectionDelegate):
    def start_request(self, server_conn, request_conn):
        return MessageDelegate(request_conn)

可调用接受单个HTTPServerRequest类型的参数:

router = RuleRouter([
    Rule(PathMatches("/callable"), request_callable)
])

def request_callable(request):
    request.write(b"HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nOK")
    request.finish()

另一个Router例子:

router = RuleRouter([
    Rule(PathMatches("/router.*"), CustomRouter())
])

当然是嵌套RuleRouter或Application允许的:

router = RuleRouter([
    Rule(HostMatches("example.com"), RuleRouter([
        Rule(PathMatches("/app1/.*"), Application([(r"/app1/handler", Handler)]))),
    ]))
])

server = HTTPServer(router)

在下面的示例中RuleRouter用于在应用程序之间进行路由:

app1 = Application([
    (r"/app1/handler", Handler1),
    # other handlers ...
])

app2 = Application([
    (r"/app2/handler", Handler2),
    # other handlers ...
])

router = RuleRouter([
    Rule(PathMatches("/app1.*"), app1),
    Rule(PathMatches("/app2.*"), app2)
])

server = HTTPServer(router)

有关应用程序级路由的更多信息,请参阅docs Application。

4.5版中的新功能。

class tornado.routing.Router[source]

抽象路由器接口。

find_handler(请求,** kwargs )[来源]

必须实现以返回HTTPMessageDelegate 可以为请求提供服务的适当实例。路由实现可以传递额外的kwargs来扩展路由逻辑。

参数:

request(httputil.HTTPServerRequest) - 当前的HTTP请求。
kwargs - 路由实现传递的其他关键字参数。

返回:

其实例HTTPMessageDelegate将用于处理请求。
class tornado.routing.ReversibleRouter[source]

路由器的抽象路由器接口,可以处理命名路由并支持将它们反转为原始URL。

reverse_url(name,* args )[来源]

返回给定路由名称和参数的url字符串,或者None如果找不到匹配项。

参数:

name(str) - 路由名称。
args - url参数。
返回:    
给定路由名称(或None)的参数化url字符串。
class tornado.routing.RuleRouter(rules = None )[来源]

基于规则的路由器实现。

从有序的规则列表构造路由器:

RuleRouter([
    Rule(PathMatches("/handler"), Target),
    # ... more rules
])

您还可以省略显式Rule构造函数并使用参数元组:

RuleRouter([
    (PathMatches("/handler"), Target),
])

PathMatches 是默认匹配器,因此上面的示例可以简化:

RuleRouter([
    ("/handler", Target),
])

在上面的示例中,Target可以是嵌套Router实例,实例 HTTPServerConnectionDelegate或旧式可调用,接受请求参数。

参数:

  • rules - 构造函数参数的Rule实例或元组列表Rule。
add_rules(规则)[来源]
  • 将新规则附加到路由器。

参数:

  • rules - Rule实例列表(或参数元组,传递给Rule构造函数)。
process_rule(规则)[来源]

重写此方法以对每个规则进行其他预处理。

参数:

  • rule(Rule) - 要处理的规则。

返回:

  • 相同或修改过的Rule实例。
  • get_target_delegate(目标,请求,** target_params )[来源]
  • 返回HTTPMessageDelegateRule的目标实例。此方法由find_handler并且可以扩展以提供其他目标类型。

参数:

  • target - 规则的目标。
  • request(httputil.HTTPServerRequest) - 当前请求。
  • target_params - 可用于HTTPMessageDelegate创建的其他参数。
  • class tornado.routing.ReversibleRuleRouter(rules = None )[来源]
  • 实现reverse_url方法的基于规则的路由器。

添加到此路由器的每个规则可以具有name可用于重建原始uri 的属性。实际的重建发生在规则的匹配器中(参见参考资料Matcher.reverse)。

class tornado.routing.Rule(matcher,target,target_kwargs = None,name = None )[来源]

路由规则。

构造一个Rule实例。

参数:

  • matcher(Matcher) - Matcher用于确定规则是否应被视为特定请求匹配的实例。
  • target - 规则的目标(通常是一个RequestHandler或 HTTPServerConnectionDelegate子类,甚至是嵌套的Router,具体取决于路由实现)。
  • target_kwargs(dict) - 在目标实例化时可能有用的参数的dict(例如,status_code 对于RequestHandler子类)。他们最终进入 target_params['target_kwargs']了RuleRouter.get_target_delegate 方法。
  • name(str) - 可用于在ReversibleRouter.reverse_url实现中查找它的规则的名称。
class tornado.routing.Matcher[source]

表示请求功能的匹配器。

match(要求)[来源]

根据请求匹配当前实例。

参数:

  • request(httputil.HTTPServerRequest) - 当前的HTTP请求

返回:

  • 的参数一个字典被传递给目标的处理程序(例如,handler_kwargs,path_args,path_kwargs 可以传递适当RequestHandler实例化)。空dict是一个有效(和常见)返回值,用于指示不使用参数传递功能时的匹配。 None必须返回以表明没有匹配。
reverse(* args )[来源]

从matcher实例和其他参数重构完整的url。

class tornado.routing.AnyMatches[source]

匹配任何请求。

class tornado.routing.HostMatches(host_pattern )[source]

匹配来自host_patternregex 指定的主机的请求。

class tornado.routing.DefaultHostMatches(application,host_pattern )[source]

匹配来自主机的请求,该请求等于应用程序的default_host。如果X-Real-Ip标题存在,则始终不返回匹配项。

class tornado.routing.PathMatches(path_pattern )[source]

使用path_patternregex 指定的路径匹配请求。

class tornado.routing.URLSpec(pattern,handler,kwargs = None,name = None )[source]

指定URL和处理程序之间的映射。

参数:

  • pattern:正则表达式匹配。正则表达式中的任何捕获组都将作为参数传递给处理程序的get / post / etc方法(如果已命名,则按关键字传递,如果未命名,则按位置传递。命名和未命名的捕获组可能不会在同一规则中混合)。
  • handler:RequestHandler要调用的子类。
  • kwargs (可选):要传递给处理程序构造函数的其他参数的字典。
  • name(可选):此处理程序的名称。使用者 reverse_url。

tornado.escape- 转义和字符串操作

HTML,JSON,URL等的转义/转义方法。

还包括一些随时间推移的其他杂项字符串操作函数。

转义函数
tornado.escape.xhtml_escape(值)[来源]
转义字符串,使其在HTML或XML中有效。

转义字符<,>,",',和&。在属性值中使用时,转义字符串必须用引号括起来。

版本3.2中已更改:将单引号添加到转义字符列表中。
tornado.escape.xhtml_unescape(值)[来源]
取消转义XML转义字符串。
tornado.escape.url_escape(value,plus = True )[来源]
返回给定值的URL编码版本。

如果plus为true(默认值),则空格将表示为“+”而不是“%20”。这适用于查询字符串,但不适用于URL的路径组件。请注意,此默认值与Python的urllib模块相反。

新的3.1版:该plus参数
tornado.escape.url_unescape(value,encoding ='utf-8',plus = True )[来源]
从URL解码给定值。

参数可以是字节或unicode字符串。

如果encoding是None,则结果将是字节字符串。否则,结果是指定编码中的unicode字符串。

如果plus为真(默认值),加号将被解释为空格(文字加号必须表示为“%2B”)。这适用于查询字符串和表单编码值,但不适用于URL的路径组件。请注意,此默认值与Python的urllib模块相反。

新的3.1版:该plus参数
tornado.escape.json_encode(值)[来源]
JSON编码给定的Python对象。
tornado.escape.json_decode(值)[来源]
返回给定JSON字符串的Python对象。
字节/ unicode转换
这些函数在Tornado中广泛使用,但大多数应用程序不应该直接使用它们。请注意,这些函数的大部分复杂性来自于Tornado支持Python 2和Python 3的事实。
tornado.escape.utf8(值)[来源]
将字符串参数转换为字节字符串。

如果参数已经是字节字符串或None,则返回不变。否则它必须是unicode字符串并编码为utf8。
tornado.escape.to_unicode(值)[来源]
将字符串参数转换为unicode字符串。

如果参数已经是unicode字符串或None,则返回不变。否则它必须是字节字符串并解码为utf8。

tornado.escape.native_str()
将字节或unicode字符串转换为类型str。相当于 utf8Python 2和to_unicodePython 3。
tornado.escape.to_basestring(值)[来源]
将字符串参数转换为basestring的子类。

在python2中,byte和unicode字符串大多可以互换,因此处理用户提供的参数和ascii字符串常量的函数可以使用任何一个并且应该返回用户提供的类型。在python3中,这两种类型不可互换,因此需要此方法将字节字符串转换为unicode。
tornado.escape.recursive_unicode(obj )[来源]
走一个简单的数据结构,将字节串转换为unicode。

支持列表,元组和词典。
杂项功能
tornado.escape.linkify(text,shorten = False,extra_params ='',require_protocol = False,allowed_protocols = ['http','https'] )[source]
使用链接将纯文本转换为HTML。

例如:会回来 linkify("Hello http://tornadoweb.org!")Hello <a href="http://tornadoweb.org">http://tornadoweb.org</a>!

参数:

- shorten:长网将缩短显示。

- extra_params:要包含在链接标记中的额外文本,或者将链接作为参数并返回额外文本的可调用文件,例如,或:linkify(text, extra_params='rel="nofollow" class="external"')

def extra_params_cb(url):
    if url.startswith("http://example.com"):
        return 'class="internal"'
    else:
        return 'class="external" rel="nofollow"'
linkify(text, extra_params=extra_params_cb)
- require_protocol:仅链接包含协议的URL。如果这是假的,那么诸如www.facebook.com之类的网址也将被链接。

- permitted_protocols:列出(或设置)应该链接的协议,例如。包含诸如的协议是非常不安全的 。linkify(text, permitted_protocols=["http", "ftp", "mailto"])javascript
tornado.escape.squeeze(值)[来源]
用单个空格替换所有空白字符序列。

tornado.locale- 国际化支持

生成本地化字符串的翻译方法。

要加载区域设置并生成已翻译的字符串:

user_locale = tornado.locale.get("es_LA")
print(user_locale.translate("Sign out"))

tornado.locale.get()返回最接近的匹配区域设置,不一定是您请求的特定区域设置。您可以使用其他参数支持复数translate(),例如:

people = [...]
message = user_locale.translate(
    "%(list)s is online", "%(list)s are online", len(people))
print(message % {"list": user_locale.list(people)})

如果是,则选择第一个字符串,否则选择第二个字符串。len(people) == 1

应用程序应调用其中一个load_translations(使用简单的CSV格式)或load_gettext_translations(使用.mo支持的格式gettext和相关工具)。如果两个方法都没有被调用,则该Locale.translate方法将只返回原始字符串。

tornado.locale.get(* locale_codes )[来源]
返回给定区域设置代码的最接近匹配项。

我们按顺序迭代所有给定的区域设置代码。如果我们对代码有一个紧密或松散的匹配(例如,“en”代表“en_US”),我们返回语言环境。否则,我们移动到列表中的下一个代码。

默认情况下,en_US如果找不到任何指定语言环境的翻译,则返回。您可以使用更改默认语言环境 set_default_locale()。
tornado.locale.set_default_locale(代码)[来源]
设置默认语言环境。

假定默认语言环境是用于系统中所有字符串的语言。从磁盘加载的转换是从默认语言环境到目标语言环境的映射。因此,您无需为默认语言环境创建转换文件。
tornado.locale.load_translations(目录,编码=无)[来源]

从目录中的CSV文件加载翻译。

翻译是具有可选的Python风格的命名占位符(例如)及其相关翻译的字符串。My name is %(name)s

该目录应具有表单的翻译文件LOCALE.csv,例如es_GT.csv。CSV文件应包含两列或三列:字符串,翻译和可选的复数指示符。多个指标应该是“复数”或“单数”之一。给定的字符串可以具有单数和复数形式。例如,取决于%(name)s是一个名称还是名称列表,可以具有不同的动词共轭。CSV文件中应该有两行用于该字符串,一行具有复数指示符“单数”,一行具有“复数”。对于没有动词在翻译时会改变的字符串,只需使用“unknown”或空字符串(或者根本不包括该列)。%(name)s liked this

使用csv默认“excel”方言中的模块读取文件。在这种格式中,逗号后面不应有空格。

如果没有encoding给出参数,如果文件包含字节顺序标记(BOM),将自动检测编码(在UTF-8和UTF-16中),如果没有BOM,则默认为UTF-8。

翻译示例es_LA.csv:

"I love you","Te amo"
"%(name)s liked this","A %(name)s les gustó esto","plural"
"%(name)s liked this","A %(name)s le gustó esto","singular"

版本4.3中已更改:已添加encoding参数。添加了对基于BOM的编码检测,UTF-16和带有BOM的UTF-8的支持。

tornado.locale.load_gettext_translations(目录,域名)[来源]

加载来自gettext语言环境树的翻译

区域设置树类似于系统/usr/share/locale,如:

{directory}/{lang}/LC_MESSAGES/{domain}.mo

翻译您的应用需要三个步骤:

  1. 生成POT翻译文件:

    xgettext --language=Python --keyword=_:1,2 -d mydomain file1.py file2.html etc

  2. 合并现有的POT文件:

    msgmerge old.po mydomain.po > new.po

  3. 编译:

    msgfmt mydomain.po -o {directory}/pt_BR/LC_MESSAGES/mydomain.mo

    tornado.locale.get_supported_locales()[来源]

    返回所有受支持的区域设置代码的列表。

class tornado.locale.Locale(代码,翻译)[来源]

表示区域设置的对象。

调用load_translationsor 之一后load_gettext_translations,调用get或get_closest获取Locale对象。

classmethod get_closest(* locale_codes )[source]

返回给定区域设置代码的最接近匹配项。

classmethod get(code )[source]

返回给定语言环境代码的Locale。

如果不支持,我们会引发异常。

translate(message,plural_message = None,count = None )[来源]

返回此语言环境的给定消息的翻译。

如果plural_message给出,您还必须提供 count。我们返回plural_message时,我们返回给定消息的单数形式 。count != 1count == 1

format_date(日期,gmt_offset = 0,相对=真,较短=假,full_format =假)[源]

格式化给定日期(应该是GMT)。

默认情况下,我们返回相对时间(例如,“2分钟前”)。您可以使用返回绝对日期字符串relative=False。

您可以强制使用完整格式的日期(“1980年7月10日”) full_format=True。

此方法主要用于过去的日期。对于未来的日期,我们将回归到完整格式。

format_day(date,gmt_offset = 0,dow = True )[来源]

将给定日期格式化为星期几。

示例:“1月22日星期一”。您可以删除星期几 dow=False。

list(部分)[来源]

返回给定列表部件的逗号分隔列表。

对于大小为1的列表,格式是例如“A,B和C”,“A和B”或仅“A”。

friendly_number(值)[来源]

返回给定整数的逗号分隔数。

class tornado.locale.CSVLocale(代码,翻译)[来源]

使用龙卷风的CSV翻译格式实现区域设置。

class tornado.locale.GettextLocale(代码,翻译)[来源]

使用gettext模块的区域设置实现。

pgettext(context,message,plural_message = None,count = None )[来源] 允许设置翻译上下文,接受复数形式。

用法示例:

pgettext("law", "right")
pgettext("good", "right")

多个消息示例:

pgettext("organization", "club", "clubs", len(clubs))
pgettext("stick", "club", "clubs", len(clubs))

要使用上下文生成POT文件,请将以下选项添加到load_gettext_translations序列的第1步:

xgettext [basic options] --keyword=pgettext:1c,2 --keyword=pgettext:1c,2,3

第一种路由改装饰器方式

import tornado
import tornado.web
import tornado.ioloop


class RouterConfig:

    def __init__(self):
        self.Application = tornado.web.Application()

    def route(self, handler):
        self.Application.add_handlers(".*$", [(handler.URL, handler)])


app = RouterConfig()


@app.route
class Main1(tornado.web.RequestHandler):
    URL = r"/"

    def get(self, *args, **kwargs):
        self.finish("ok")


if __name__ == '__main__':
    app.Application.listen(8000)
    tornado.ioloop.IOLoop.instance().start()

第二种路由改装饰器方式

import tornado.web
import tornado.ioloop


class Route(object):

    def __init__(self):
        self.urls = list()

    def __call__(self, url, *args, **kwargs):
        def register(cls):
            self.urls.append((url, cls))
            return cls
        return register


route = Route()


@route(r"/")
class Main2(tornado.web.RequestHandler):

    def get(self, *args, **kwargs):
        self.finish("ok")


if __name__ == '__main__':
    app = tornado.web.Application(route.urls)
    app.listen(8000)
    tornado.ioloop.IOLoop.instance().start()

第三种路由改装饰器方式

import tornado.web
import tornado.ioloop


class RouterConfig(tornado.web.Application):

    def route(self, url):
        def register(handel):
            self.add_handlers(".*$", [(url, handel)])
            return handel
        return register


app = RouterConfig(cookie_secret="ulb7bEIZmwpV545Z")


@app.route(r"/")
class Main3(tornado.web.RequestHandler):

    def get(self, *args, **kwargs):
        self.finish("ok")


if __name__ == '__main__':
    app.listen(8000)
    tornado.ioloop.IOLoop.instance().start()
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Easter79 Easter79
3年前
vue+element 表格formatter数据格式化并且插入html标签
前言   vue中element框架,其中表格组件,我既要行内数据格式化,又要插入html标签一贯思维,二者不可兼得也一、element表格数据格式化  !(https://oscimg.oschina.net/oscnet/3c43a1cb3cbdeb5b5ad58acb45a42612b00.p
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Wesley13 Wesley13
3年前
4cast
4castpackageloadcsv.KumarAwanish发布:2020122117:43:04.501348作者:KumarAwanish作者邮箱:awanish00@gmail.com首页:
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
隔壁老王
隔壁老王
Lv1
千万程序员队伍中的一员。我住隔壁我姓王,同事们亲切得称呼我隔壁老王
文章
20
粉丝
2
获赞
7