[tornado]入门tornado(1): 项目结构

学习资料

  1. tornado-bolierplate据说是一个适合新手入门的项目,但是已经是14年前的项目了, 使用的tornado版本是3.2(而现在tornado已经到6.4了),所以这个项目对我来说更多是学习工作流程以及项目结构
  2. iwokh blog以及这一篇2020年的博客, 时间稍微近一点

本文主要是搞清楚一个tornado app的大致结构, 通过结构出发来理解各模块的作用, 毕竟有那么多项目, 如果连结构都看不懂, 连各个模块是干嘛的, 那接下去的学习肯定更困难了

项目结构

首先从readme开始, 了解一个tornado项目的结构 (tornaod-bolierplate)

tornado-boilerplate/
    handlers/
        foo.py
        base.py
    lib/
    logconfig/
    media/
        css/
            vendor/
        js/
            vendor/
        images/
    requirements/
        common.txt
        dev.txt
        production.txt
    templates/
    vendor/
    environment.py
    fabfile.py
    app.py
    settings.py

其中涉及的一些文件的用处

网页接口的处理 - handlers (重要)

所有RequestHandler都在这里, 当environment.py执行时, pythonpath会得到相应的更新;

  • 所有handler都应该是继承自tornado.web.RequestHandler, 然后在这些handler内部重写rest的接口
# 像这样...
class HelloWorldHandlerTwo(web.RequestHandler):
	def get(self, *args, **kwargs):
		self.write("hello world---two")

tornado-boilerplate中的例子, 可以说明handler的作用

# 已创建基类
# 创建一个handler
class FooHandler(BaseHandler):
    def get(self):
        self.render("base.html")

其中渲染的base.html就是网页的主html文件, 相当于index.html的地位
handler还有更多细节, 看官方文档

  • handler中不要写同步的方法, 会被阻塞

列举地址集 - urls.py

在这里列举所有的url以及对应的handler, url的写法遵循python的正则表达式

  • r"/foo"指代所有以/foo开头的地址
url_patterns = [
    (r"/foo", FooHandler),
]
  • 注意数组里的是urlSpec对象, 可接受三个参数 -- 路径的正则表达式, 对应handler, 传给initialize方法的参数(字典格式)
# database会最后传入handler的initialize方法里, 具体去看 https://www.cnblogs.com/Akira300000/p/18004093
url_patterns = [
    (r'/user/(.*)', ProfileHandler, dict(database=database)),
]

启动项目 - app.py

需要一个启动类app.py, 注意我们这里用的python是3.10之前的版本
tornado-bolierplate里的启动类是这样写的 (14年前的代码了, 其实也可以用)

#!/usr/bin/env python
import tornado.httpserver
from tornado import options, web, ioloop

from settings import settings
from urls import url_patterns
# 创建一个类继承web.Application, 并指定初始化方法
class TornadoBoilerplate(tornado.web.Application):
    def __init__(self):
        tornado.web.Application.__init__(self, url_patterns, **settings)
# 创建主入口, 首先创建对象, 然后监听动态端口
def main():
    app = TornadoBoilerplate()
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

if __name__ == "__main__":
    main()

而现在启动类的写法或许被简化了一点⬇️但逻辑是不变的

# 定义动态参数, 指定名称, 默认值, 数据类型
options.define("port", default="8888", type=int, help="端口号")
options.define("static_path", default="static", type=str, help="静态资源路径")

# 创建一个继承web.Application的对象, 传入参数, 监听动态对象
if __name__ == '__main__':
    app = web.Application(url_map, debug=True)
    app.listen(options.port)
    print('tornado, 启动')
    ioloop.IOLoop.current().start()

启动的时候就指令行输入python option_demo.py --port=8080指定端口号
但是从3.10版本开始, 这样的启动方式可能会报错; 根据官方文档, 更推荐使用异步io写法

# python3.10之后推荐的写法
async def main():
    app = web.Application(url_map)
    app.listen(options.port)
    shutdown_event = asyncio.Event()
    await shutdown_event.wait()

if __name__ == "__main__":
    asyncio.run(main())

lib

一些包和模块, 这些东西并不是handler, 而是一些python类和方法; 同样地, 当environment.py执行时, pythonpath会得到相应的更新

logconfig

(谷歌翻的, 太长不看系列)
该包包含一个initialize_logging方法,该方法从项目的settings.py中调用,用于设置Python的日志系统;
服务器部署的默认设置是登录到syslog, 单独开发的默认设置是简单地登录到控制台。
所有记录器都应该是应用程序根记录器的子级(在settings.py中定义)。在每个需要日志功能的文件顶部加上:

import logging
logger = logging.getLogger('five.' + __name__)

media

包含css/, js/和image/文件夹, 第三方库就放在vendor/里, 这样可以和自己打的代码分开

requirements

用到的软件/库/包的版本号

templates

存放要用到的html文件

示例代码

最后拜托AI生成一段简单代码

# 一个简单的tornado app, 需要使用配置文件里的端口号, 使用tornado-6.2
import tornado.ioloop
import tornado.web
import configparser

# Read configuration file
config = configparser.ConfigParser()
config.read('config.ini')  # Assuming a file named 'config.ini'
port = int(config['server']['port'])  # Read port from 'server' section

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world! This server is running on port " + str(port))

# 这里的方式和boilerplate是一样的
def make_app():
    return tornado.web.Application([
        (r"/", MainHandler),
    ])

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

配置文件

[server]
port = 8888  # Replace with your desired port

将配置文件和app.py放在相同路径下, 然后指令行输入python app.py
tips

  • configparser是python自带的ini文件操作模块, 也可以在这里用来读取config.ini
  • 也可以用tornado自带的options包
from tornado.options import define, options

# Parse configuration file
options.parse_config_file("config.ini")
# inside main function
app.listen(options.port)
posted @ 2024-02-03 16:33  Akira300000  阅读(33)  评论(0编辑  收藏  举报