Tornado - 请求与响应

整理基础工程

目录层级

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
project                 # 工程总目录
ORM # 对象关系映射目录
__init__.py # 包文件
orm.py # 数据库处理文件
sunckMysql.py # 数据库处理文件
static # 静态文件目录
css # css文件目录
html # 静态页面目录
index.html # 首页文件
img # 图片文件目录
js # js文件目录
templates # 模板文件目录
upfile # 上传文件目录
views # 视图文件目录
__init__.py # 包文件
index.py # 视图文件
application.py # 路由文件
config.py # 配置文件
models.py # 数据模型文件
server.py # 服务文件

以后写新项目直接拷贝基础工程即可!

基础工程

  • ORM

    • __init__.py:空文件即可。
    • orm.py
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      from .sunckMysql import SunckMySQL


      class ORM():
      def save(self):
      # insert into students (name,age) values('tyui',32)
      tableName = (self.__class__.__name__).lower()
      fieldsStr = valuesStr = "("
      for field in self.__dict__:
      fieldsStr += (field + ",")
      if isinstance(self.__dict__[field], str):
      valuesStr += ("'" + self.__dict__[field] + "',")
      else:
      valuesStr += (str(self.__dict__[field]) + ",")
      fieldsStr = fieldsStr[:len(fieldsStr) - 1] + ")"
      valuesStr = valuesStr[:len(valuesStr) - 1] + ")"
      sql = "insert into " + tableName + " " + fieldsStr + " values " + valuesStr
      # print(sql)
      db = SunckMySQL()
      # db2 = SunckMySQL()
      # print(db is db2)
      db.insert(sql)

      def delete(self):
      pass

      def update(self):
      pass

      @classmethod
      def all(cls):
      # select * from students
      tableName = (cls.__name__).lower()
      sql = "select * from " + tableName
      db = SunckMySQL()
      # print(sql)
      return db.get_all_obj(sql, tableName)

      @classmethod
      def filter(cls):
      pass
    • sunckMysql.py
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      import pymysql
      import config


      def singleton(cls, *args, **kwargs):
      instances = {}

      def _singleton():
      if cls not in instances:
      instances[cls] = cls(*args, **kwargs)
      return instances[cls]

      return _singleton


      @singleton
      class SunckMySQL():
      host = config.mysql["host"]
      user = config.mysql["user"]
      passwd = config.mysql["passwd"]
      dbName = config.mysql["dbName"]

      def connet(self):
      self.db = pymysql.connect(self.host, self.user, self.passwd, self.dbName)
      self.cursor = self.db.cursor()

      def close(self):
      self.cursor.close()
      self.db.close()

      def get_one(self, sql):
      res = None
      try:
      self.connet()
      self.cursor.execute(sql)
      res = self.cursor.fetchone()
      self.close()
      except:
      print("查询失败")
      return res

      def get_all(self, sql):
      res = ()
      try:
      self.connet()
      self.cursor.execute(sql)
      res = self.cursor.fetchall()
      self.close()
      except:
      print("查询失败")
      return res

      def get_all_obj(self, sql, tableName, *args):
      resList = []
      fieldsList = []
      if (len(args) > 0):
      for item in args:
      fieldsList.append(item)
      else:
      fieldsSql = "select COLUMN_NAME from information_schema.COLUMNS where table_name = '%s' and table_schema = '%s'" % (
      tableName, self.dbName)
      fields = self.get_all(fieldsSql)
      for item in fields:
      fieldsList.append(item[0])

      # 执行查询数据sql
      res = self.get_all(sql)
      for item in res:
      obj = {}
      count = 0
      for x in item:
      obj[fieldsList[count]] = x
      count += 1
      resList.append(obj)
      return resList

      def insert(self, sql):
      return self.__edit(sql)

      def update(self, sql):
      return self.__edit(sql)

      def delete(self, sql):
      return self.__edit(sql)

      def __edit(self, sql):
      count = 0
      try:
      self.connet()
      count = self.cursor.execute(sql)
      self.db.commit()
      self.close()
      except:
      print("事物提交失败")
      self.db.rollback()
      return count
  • views

    • __init__.py:空文件即可。
    • index.py
      1
      2
      3
      4
      5
      6
      7
      8
      import tornado.web
      from tornado.web import RequestHandler


      class StaticFileHandler(tornado.web.StaticFileHandler):
      def __init__(self, *args, **kwargs):
      super(StaticFileHandler, self).__init__(*args, **kwargs)
      self.xsrf_token
  • application.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import os
    import config
    import tornado.web
    from views import index


    class Application(tornado.web.Application):
    def __init__(self):
    handlers = [
    # 静态页面路由,其它路由写在该路由上边
    (r'/(.*)$', index.StaticFileHandler,
    {'path': os.path.join(config.BASE_DIRS, 'static/html'), 'default_filename': 'index.html'})
    ]
    super(Application, self).__init__(handlers, **config.settings)
  • config.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    import os

    BASE_DIRS = os.path.dirname(__file__)

    # 参数
    options = {
    'port': 8000,
    }

    # 数据库配置
    mysql = {
    'host': 'IP',
    'user': '用户名',
    'passwd': '密码',
    'dbName': '数据库名'
    }

    # 配置
    settings = {
    'debug': True,
    'xsrf_cookies': True,
    'static_path': os.path.join(BASE_DIRS, 'static'),
    'template_path': os.path.join(BASE_DIRS, 'templates'),
    'cookie_secret': 'wtsaTrAfTBuZTx5f9yBhX8ZVZ479HknqnSMKKAmau+0=',
    }
  • models.py

    1
    2
    3
    4
    5
    6
    7
    from ORM.orm import ORM

    '''
    class ClassName(ORM):
    def __init__(self):
    pass
    '''
  • server.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import config
    import tornado.ioloop
    import tornado.httpserver
    from application import Application

    if __name__ == '__main__':
    app = Application()
    httpServer = tornado.httpserver.HTTPServer(app)
    httpServer.bind(config.options['port'])
    httpServer.start(1)

    tornado.ioloop.IOLoop.current().start()
  • static -> html -> index.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Tornado</title>
    </head>
    <body>
    <h1 style="text-align: center">Welcome to Tornado!</h1>
    </body>
    </html>
  • ⚠️注意:我没写的文件或目录即为空文件或目录,直接创建即可!

Application

settings

  • debug
    • 作用:设置 tornado 是否工作在调试模式下,默认为 False,即工作在生产模式下。
    • True 的特性
      • 自动重启:
        • tornado 应用会监控源代码文件,当有保存改动时便会重启服务器,可以减少手动重启的次数,提高开发效率。
        • 如果保存后代码有错误会导致重启失败,修改错误后需要手动重启。
        • 可以通过 autoreload = True 设置
      • 取消缓存编译的模板:可以通过 compiled_template_cache = False 单独设置
      • 取消缓存静态文件的 hash 值:可以通过 static_hash_cache = False 单独设置
      • 提供追踪信息:可以通过 server_traceback = True 单独设置
  • static_path:设置静态文件目录
  • template_path:设置模板文件目录
  • autoescape:当未 None 时关闭当前项目的自动转义,一般不建议使用
  • cookie_secret:配置安全 cookie 秘钥
  • xsrf_cookies:当为 True 开启 XSRF 保护
  • login_url:用户验证失败会映射该路由
  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import os

    BASE_DIRS = os.path.dirname(__file__)

    # 参数
    options = {
    'port': 9000,
    }

    # 配置
    settings = {
    'debug': False,
    'xsrf_cookies': True,
    'login_url': '/login',
    'static_path': os.path.join(BASE_DIRS, 'static'),
    'template_path': os.path.join(BASE_DIRS, 'templates'),
    'cookie_secret': 'wtsaTrAfTBuZTx5f9yBhX8ZVZ479HknqnSMKKAmau+0=',
    }

路由

  • (r'/', index.IndexHandler)
  • (r'/sunck', index.SunckHandler, {'word1': 'nice', 'word2': 'handsome'})
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class SunckHandler(RequestHandler):
    # 该方法会在HTTP方法之前调用
    def initialize(self, word1, word2):
    self.word1 = word1
    self.word2 = word2

    def get(self, *args, **kwargs):
    print(self.word1, self.word2)
    self.write('Sunck is a good man!')

    ⚠️注意:需要重写 initialize 方法接收传递的参数

  • tornado.web.url(r'/kaige', index.KaigeHandler, {"word3": "handsome", "word4": "cool"}, name="index")
    1
    2
    3
    4
    5
    6
    7
    8
    class KaigeHandler(RequestHandler):
    def initialize(self, word3, word4):
    self.word3 = word3
    self.word4 = word4

    def get(self, *args, **kwargs):
    print(self.word3, self.word4)
    self.write("kaige is a nice man")

    ⚠️注意:如果使用 name 属性,不能使用元组路由,需要使用 tornado.web.url 定义路由

  • 反向解析
    1
    tornado.web.url(r'/home', index.KaigeHandler, {"word3": "handsome", "word4": "cool"}, name="kaigegood")
    1
    2
    3
    4
    5
    class IndexHandler(RequestHandler):
    def get(self, *args, **kwargs):
    self.write('Hello world!')
    url = self.reverse_url('kaigegood')
    self.write("<a href='%s'>去另一个界面</a>" % (url))

    self.reverse_url('kaigegood'):会获取到 name"kaigegood" 的路由的正则匹配

  • 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    import tornado.web
    from views import index
    import config


    class Application(tornado.web.Application):
    def __init__(self):
    handlers = [
    (r'/', index.IndexHandler),
    (r'/home', index.HomeHandler),
    (r'/sunck', index.SunckHandler, {'word1': 'nice', 'word2': 'handsome'}),
    # tornado.web.url(r'/kaige', index.KaigeHandler, {"word3": "handsome", "word4": "cool"}, name="index"),
    tornado.web.url(r'/home', index.KaigeHandler, {"word3": "handsome", "word4": "cool"}, name="kaigegood"),
    ]
    super(Application, self).__init__(handlers, **config.settings)

    application.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    import tornado.web
    from tornado.web import RequestHandler


    class IndexHandler(RequestHandler):
    def get(self, *args, **kwargs):
    self.write('Hello world!')
    url = self.reverse_url('kaigegood')
    self.write("<a href='%s'>去另一个界面</a>" % (url))


    class HomeHandler(RequestHandler):
    def get(self, *args, **kwargs):
    self.write('Welcome to home!')


    class SunckHandler(RequestHandler):
    # 该方法会在HTTP方法之前调用
    def initialize(self, word1, word2):
    self.word1 = word1
    self.word2 = word2

    def get(self, *args, **kwargs):
    print(self.word1, self.word2)
    self.write('Sunck is a good man!')


    class KaigeHandler(RequestHandler):
    def initialize(self, word3, word4):
    self.word3 = word3
    self.word4 = word4

    def get(self, *args, **kwargs):
    print(self.word3, self.word4)
    self.write("kaige is a nice man")

    index.py

tornado.web.RequestHandler

利用 HTTP 协议向服务器传递参数

  • 提取 URI 的特定部分:http://127.0.0.1:8000/liuyifei/good/nice/handsom

    • (r'/liuyifei/(\w+)/(\w+)/(\w+)', index.LiuyifeiHandler)

      1
      2
      3
      4
      class LiuyifeiHandler(RequestHandler):
      def get(self, p1, p2, p3, *args, **kwargs):
      print(p1 + "-" + p2 + "-" + p3)
      self.write("liuyifei is a nice women")
    • (r'/liuyifei/(?P<p1>\w+)/(?P<p3>\w+)/(?P<p2>\w+)', index.LiuyifeiHandler)

      1
      2
      3
      4
      class LiuyifeiHandler(RequestHandler):
      def get(self, p1, p2, p3, *args, **kwargs):
      print(p1 + "-" + p2 + "-" + p3)
      self.write("liuyifei is a nice women")
  • get 方式传递参数

    • http://127.0.0.1:8000/zhangmanyu?a=1&b=2&c=3
      • self.get_query_argument(name, default=ARG_DEFAULT, strip=True)
      • 参数
        • name
          • 从 get 请求参数字符串中返回指定参数的值
          • 如果出现过个同名参数,返回最后一个值
        • default
          • 设置未传的 name 参数时返回默认的值,如果 default 也没有设置,会抛出 tornado.web.MissingArgumentError 异常
        • strip
          • 表示是否过滤掉左右两边的空白字符,默认为 True 过滤
      • 示例
        1
        2
        3
        4
        5
        6
        7
        class ZhangmanyuHandler(RequestHandler):
        def get(self, *args, **kwargs):
        a = self.get_query_argument("a")
        b = self.get_query_argument("b")
        c = self.get_query_argument("c", strip=False)
        print(a, b, "*" + c + "*")
        self.write("zhangmanyu is a good women")
    • http://127.0.0.1:8000/zhangmanyu?a=1&a=2
      • self.get_query_arguments(name, strip=True)
      • 参数:同上
      • 示例
        1
        2
        3
        4
        5
        class ZhangmanyuHandler(RequestHandler):
        def get(self, *args, **kwargs):
        alist = self.get_query_arguments("a")
        print(alist[0], alist[1])
        self.write("zhangmanyu is a good women")
  • post 方式传递参数

    • self.get_body_argument(name, default=ARG_DEFAULT, strip=True)
    • self.get_body_arguments(name, strip=True)
    • 示例:(r'/postfile', index.PostFileHandler)
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      class PostFileHandler(RequestHandler):
      def get(self, *args, **kwargs):
      self.render('postfile.html')

      def post(self, *args, **kwargs):
      name = self.get_body_argument("username")
      passwd = self.get_body_argument("passwd")
      hobbyList = self.get_body_arguments("hobby")
      print(name, passwd, hobbyList)
      self.write("sunck is a handsome man")

      index.py

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      <!DOCTYPE html>
      <html lang="en">
      <head>
      <meta charset="UTF-8">
      <title>Title</title>
      </head>
      <body>
      <form action="/postfile" method="post">
      姓名:<input type="text" name="username"/>
      <hr/>
      密码:<input type="password" name="passwd"/>
      <hr/>
      爱好:
      <input type="checkbox" value="power" name="hobby">权利
      <input type="checkbox" value="money" name="hobby">金钱
      <input type="checkbox" value="book" name="hobby">
      <input type="submit" value="登陆"/>
      </form>
      </body>
      </html>

      templates -> postfile.html

  • 即可以获取 get 请求,也可以获取 post 请求

    • self.get_argument(name, default=ARG_DEFAULT, strip=True)
    • self.get_argument(name, strip=True)
    • ⚠️注意:一般不会选用
  • 在 http 报文的头中增加自定义的字段

request 对象

  • 作用:存储了关于请求的相关信息
  • 属性:http://127.0.0.1:8000/zhuyin?a=1&b=2
    • method:HTTP 请求的方式
    • host:被请求的主机名
    • uri:请求的完整资源地址,包括路径和 get 查询参数部分,如:/zhuyin?a=1&b=2
    • path:请求的路径部分,如:/zhuyin
    • query:请求参数部分,如:a=1&b=2
    • version:使用的 HTTP 版本,如:HTTP/1.1
    • headers:请求的协议头,是一个字典类型
    • body:请求体数据
    • remote_ip:客户端的 ip
    • files:用户上传的文件,字典类型
      1
      2
      3
      4
      5
      6
      7
      8
      9
      {
      'file': [
      {
      'filename': 'a.txt',
      'body': b'sunck is a good man',
      'content_type': 'text/plain'
      }
      ]
      }
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      {
      'file': [
      {
      'filename': 'a.txt',
      'body': b'sunck is a good man',
      'content_type': 'text/plain'
      },
      {
      'filename': 'b.txt',
      'body': b'sunck is a nice man',
      'content_type': 'text/plain'
      }
      ]
      }
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      {
      'file': [
      {
      'filename': 'a.txt',
      'body': b'sunck is a good man',
      'content_type': 'text/plain'
      },
      {
      'filename': 'b.txt',
      'body': b'sunck is a nice man',
      'content_type': 'text/plain'
      }
      ],
      'img': [
      {
      'filename': 'tornado高效原理图.png',
      'body': b'qwertyuiosdghj',
      'content_type': 'image/png'
      }
      ]
      }
  • 示例:(r'/zhuyin', index.ZhuyinHandler)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class ZhuyinHandler(RequestHandler):
    def get(self, *args, **kwargs):
    print(self.request.method)
    print(self.request.host)
    print(self.request.uri)
    print(self.request.path)
    print(self.request.query)
    print(self.request.version)
    print(self.request.headers)
    print(self.request.body)
    print(self.request.remote_ip)
    print(self.request.files)
    self.write("zhuyin is a good women")

tornador.httputil.HTTPFile 对象

  • 作用:是接收到的文件对象
  • 属性
    • filename:文件的实际名字
    • body:文件的数据实体
    • content_type:文件的类型
  • 示例:(r'/linqingxia', index.UpFileHandler)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import os
    import config


    class UpFileHandler(RequestHandler):
    def get(self, *args, **kwargs):
    self.render('upfile.html')

    def post(self, *args, **kwargs):
    filesDict = self.request.files
    for inputname in filesDict:
    fileArr = filesDict[inputname]
    for fileObj in fileArr:
    # 存储路径
    filePath = os.path.join(config.BASE_DIRS, 'upfile/' + fileObj.filename)
    with open(filePath, "wb") as f:
    f.write(fileObj.body)
    self.write("ok")

    index.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>上传文件</title>
    </head>
    <body>
    <form method="post" action="/linqingxia" enctype="multipart/form-data">
    <input type="file" name="file"/>
    <input type="file" name="file"/>
    <input type="file" name="img"/>
    <input type="submit" value="上传"/>
    </form>
    </body>
    </html>

    templates -> upfile.html

响应输出

write

  • 原型:self.write(chunk)
  • 作用:将 chunk 数据写到输出缓冲区
  • 图示
    缓冲区
  • 基础:(r'/write', index.WriteHandler)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class WriteHandler(RequestHandler):
    def get(self, *args, **kwargs):
    self.write("sunck is a good man")
    self.write("sunck is a nice man")
    self.write("sunck is a handsome man")
    # 刷新缓冲区,关闭当次请求通道
    self.finish()
    # 在finish下边就不要再write
    # self.write("sunck is a cool man")
  • 利用 write 方法写 json 数据
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import json


    class Json1Handler(RequestHandler):
    def get(self, *args, **kwargs):
    per = {
    "name": "sunck",
    "age": 18,
    "height": 175,
    "weight": 70
    }
    # 将字典转换成json字符串
    jsonStr = json.dumps(per)
    self.write(jsonStr)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Json2Handler(RequestHandler):
    def get(self, *args, **kwargs):
    per = {
    "name": "kaige",
    "age": 18,
    "height": 175,
    "weight": 70
    }
    self.write(per)

    ⚠️注意:自己手动序列化 Json 方式 Content-Type 属性值为 text/html,而采用 write 自动序列化方式,Content-Type 属性为 application/json

self.set_header(name, value)

  • 作用:手动设置一个名为 name,值为 value 的响应头字段
  • 参数
    • name:字段名称
    • value:字段值
  • 示例:(r'/json1', index.Json1Handler)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import json


    class Json1Handler(RequestHandler):
    def get(self, *args, **kwargs):
    per = {
    "name": "sunck",
    "age": 18,
    "height": 175,
    "weight": 70
    }
    # 将字典转换成json字符串
    jsonStr = json.dumps(per)
    self.set_header("Content-Type", "application/json; charset=UTF-8")
    self.set_header("sunck", "good")
    self.write(jsonStr)

set_default_headers()

  • 作用:在进入 HTTP 响应处理方法之前被调用,可以重写该方法来预先设置默认的 headers
  • ⚠️注意:在 HTTP 处理方法中使用 set_header 设置的字段会覆盖 set_default_headers() 里设置的默认字段的值
  • 示例:(r'/header', index.HeaderHandler)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class HeaderHandler(RequestHandler):
    def set_default_headers(self):
    self.set_header("Content-Type", "text/html; charset=UTF-8")
    self.set_header("kaige", "nice")

    def get(self, *args, **kwargs):
    self.set_header("kaige", "handsome")
    self.write("good nice")

    def post(self, *args, **kwargs):
    pass

self.set_status(status_code, reason=None)

  • 作用:为响应设置状态码
  • 参数:
    • status_code
      • 状态码值,为 int 类型
      • 如果 reason 的值为 None,则状态码必须为正常值
    • reason:描述状态码的词组,string 类型
  • 示例:(r'/status', index.StatusCodeHandler)
    1
    2
    3
    4
    class StatusCodeHandler(RequestHandler):
    def get(self, *args, **kwargs):
    self.set_status(404)
    self.write("************************")
    1
    2
    3
    4
    class StatusCodeHandler(RequestHandler):
    def get(self, *args, **kwargs):
    self.set_status(999, "who?where?what?")
    self.write("************************")
    1
    2
    3
    4
    5
    class StatusCodeHandler(RequestHandler):
    def get(self, *args, **kwargs):
    self.write("************************")
    # 会报错
    self.set_status(999)

self.redirect(url):重定向

  • 作用:重定向到 url 网址
  • 示例:(r'/index', index.RedirectHandler)
    1
    2
    3
    class RedirectHandler(RequestHandler):
    def get(self, *args, **kwargs):
    self.redirect("/")

self.send_error(status_code=500, **kwargs)

  • 作用:抛出 HTTP 错误状态码,默认为 500,抛出错误后 tornado 会调用 wirte_error() 方法进行处理,并返回给浏览器错误界面
  • ⚠️注意:在 send_error 之下就不要在响应输出了

wirte_error(status_code, **kwargs)

  • 作用:用来处理 send_error 抛出的错误信息,并返回给浏览器错误界面
  • 示例:(r'/iserror', index.ErrorHandler)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class ErrorHandler(RequestHandler):
    def write_error(self, status_code, **kwargs):
    if status_code == 500:
    code = 500
    # 返回500界面
    self.write("服务器内部错误")
    elif status_code == 404:
    code = 404
    # 返回404界面
    self.write("资源不存在")
    self.set_status(code)

    def get(self, *args, **kwargs):
    flag = self.get_query_argument("flag")
    print(type(flag))
    if flag == '0':
    self.send_error(404)
    self.write("you are right")