You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bottle框架before_request钩子在多模块合并场景下未触发问题

问题原因分析

这个问题的核心在于Bottle的merge()方法默认仅合并路由规则,不会自动合并钩子(hook)、错误处理器这类附加回调。这就是为什么你的@_local_bottle.get路由能正常工作,但before_request钩子被忽略的原因——路由是merge()的默认处理对象,而钩子不在其处理范围内。

解决方案:手动合并子应用的钩子

你需要在合并子Bottle实例到主应用时,手动遍历子实例的钩子列表,将它们注册到主应用中。Bottle的每个应用实例都有一个hooks属性,这是一个字典,键是钩子名称(比如before_request),值是该钩子对应的回调函数列表。

修改你的start.py中的合并逻辑,添加钩子合并的代码:

def start_server(debug=False):
    app, logger = setup_app(debug)
    logger.debug("Importing applications.")
    import ps_web_apps.load_modules
    for module, ps_bottle in ps_web_apps.load_modules.get_bottle_list():
        logger.debug("Importing application '%s'.", module)
        # 先合并路由
        app.merge(ps_bottle)
        # 手动合并所有钩子到主应用
        for hook_name, callbacks in ps_bottle.hooks.items():
            for callback in callbacks:
                app.add_hook(hook_name, callback)
    app = SessionMiddleware(app, session_opts)
    logger.debug("Starting server.")
    sys.argv[1:] = ["--workers", num_of_workers, "--timeout", gunicorn_timeout]
    if enable_gevent:
        logger.debug("Started as asyc gevent server.")
        bottle.run(app=app, port=8081, server='gunicorn', worker_class='gevent', debug=debug, quiet=not debug)
    else:
        bottle.run(app=app, port=8081, server='gunicorn', debug=debug, quiet=not debug)
额外说明
  • 这个方法不仅适用于before_request,对after_request、app_error等其他Bottle钩子同样有效,会自动合并所有子应用的钩子。
  • 如果你的子应用有重复的钩子逻辑,合并后会按注册顺序依次执行(主应用原有钩子先执行,然后是子应用的钩子)。
  • 如果你不想合并所有钩子,也可以针对性地只合并before_request:
    # 仅合并before_request钩子
    if 'before_request' in ps_bottle.hooks:
        for callback in ps_bottle.hooks['before_request']:
            app.add_hook('before_request', callback)
    

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 15:22:54