You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Tornado中initialize()与prepare()方法的区别及适用场景解析

Great question! I remember scratching my head over this exact distinction when I first started building apps with Tornado—they do seem interchangeable at first glance, but they have clear use cases once you dig into the details. Let’s break it down:

Core Differences & Use Cases

initialize(): Instance Setup for Static Configuration

initialize() is called once per RequestHandler instance (and since Tornado creates a new instance for every HTTP request, this means it runs once per request—but its purpose is distinct from prepare()).

The key feature of initialize() is that it can accept arguments passed directly from your route definitions. This makes it perfect for injecting static dependencies or configuration that the handler needs to function across all requests it handles.

Example Use Case: Injecting Dependencies

Suppose you have a database connection multiple handlers need access to. You can pass it via the route and capture it in initialize():

import tornado.web

class UserHandler(tornado.web.RequestHandler):
    def initialize(self, db_connection):
        # Save the injected database connection as an instance variable
        self.db = db_connection

    def get(self, user_id):
        # Use the pre-configured DB connection in your request handler
        user = self.db.fetch_user(user_id)
        self.write({"user": user})

# Route definition: pass the DB connection as an argument
app = tornado.web.Application([
    (r"/users/(\d+)", UserHandler, {"db_connection": my_db_instance}),
])

Other solid uses for initialize():

  • Setting up handler-specific template paths or static file roots
  • Capturing route-specific flags (like a require_admin toggle for permission checks)

prepare(): Per-Request Preprocessing

prepare() is called before every request method (GET, POST, PUT, etc.)—no exceptions. Even if you redirect or send an error response, prepare() will run first.

This is your go-to method for logic that needs to execute for every single request handled by the handler, regardless of the HTTP method.

Example Use Case: Enforcing Authentication

If you want to ensure a user is logged in before accessing any endpoint in a handler, put the auth check in prepare() instead of duplicating it in every get()/post() method:

class ProtectedHandler(tornado.web.RequestHandler):
    def prepare(self):
        # Check if the user has a valid session cookie
        user_id = self.get_secure_cookie("authenticated_user")
        if not user_id:
            # Redirect to login if not authenticated
            self.redirect("/login")
            return
        # Fetch the user and store it for use in request methods
        self.current_user = self.db.fetch_user(user_id)

    def get(self):
        # No need to re-check auth here—prepare() already handled it
        self.render("dashboard.html", user=self.current_user)

    def post(self):
        # Same here: user is guaranteed to be authenticated
        self.db.update_user(self.current_user.id, self.get_argument("name"))

Other great uses for prepare():

  • Parsing custom request body formats (e.g., non-standard JSON or XML that Tornado doesn’t parse by default)
  • Logging request metadata (IP address, user agent, request timestamp)
  • Validating mandatory request headers required for all endpoints

Quick Summary

Aspectinitialize()prepare()
ArgumentsAccepts route-passed parametersNo arguments (except self)
Call TimingOnce per handler instance (per request)Before every request method (per request)
Primary PurposeInject static dependencies/configDynamic per-request preprocessing
Common Use CasesDB connections, route-specific settingsAuth checks, request parsing, logging

内容的提问来源于stack exchange,提问作者Lore

火山引擎 最新活动