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

如何整合Flask应用与Click CLI组?遇TypeError问题求助

Flask CLI 与 Click 上下文传参的兼容方案

单独使用 Click 时,以下代码可正常通过上下文传递参数:

import click

@click.group()
@click.option('-x', default='xx', help="set x")
@click.option('-y', default='yy', help="set y")
@click.pass_context
def cli(ctx, **kwargs):
  ctx.obj.update(**kwargs)

@cli.command()
@click.pass_context
def foo(ctx):
  print(ctx.obj['a'])
  print(ctx.obj['b'])

if __name__ == "__main__":
  cli(obj={'b':'bar'})

但将命令组挂载到 Flask 的 @app.cli.group() 后,运行时会抛出错误:

TypeError: 'ScriptInfo' object is not subscriptable

对应代码:

import flask
import click

app = flask.Flask(__name__)

@app.cli.group()
@click.option('-x', default='xx', help="set x")
@click.option('-y', default='yy', help="set y")
@click.pass_context
def cli(ctx, **kwargs):
  ctx.update(**kwargs)

@cli.command()
@click.pass_context
def foo(ctx):
  print(ctx.obj['a'])
  print(ctx.obj['b'])

if __name__ == "__main__":
  cli(obj={'b':'bar'})

问题根源

Flask 的 CLI 集成中,ctx.obj 默认是 flask.cli.ScriptInfo 实例,而非原生 Click 使用的普通字典。该对象用于管理 Flask 应用的创建与配置,直接用下标访问会触发类型错误,且原代码中 ctx.update() 的调用方式也不符合 Flask CLI 的上下文逻辑。


解决方案

方案1:利用 ScriptInfo 的 data 属性存储自定义参数

Flask 为 ScriptInfo 内置了 data 属性,专门用于存放自定义上下文数据,以此实现参数传递:

import flask
import click
from flask.cli import ScriptInfo

app = flask.Flask(__name__)

@app.cli.group()
@click.option('-x', default='xx', help="set x")
@click.option('-y', default='yy', help="set y")
@click.pass_context
def cli(ctx, x, y):
    # 初始化 data 字典,避免首次访问时不存在
    if not hasattr(ctx.obj, 'data'):
        ctx.obj.data = {}
    # 将命令行参数存入 data
    ctx.obj.data.update({'x': x, 'y': y})

@cli.command()
@click.pass_context
def foo(ctx):
    # 从 ScriptInfo 的 data 中读取参数
    print(ctx.obj.data.get('x'))
    print(ctx.obj.data.get('b'))

if __name__ == "__main__":
    # 启动时传入自定义数据到 ScriptInfo
    info = ScriptInfo(create_app=lambda: app, data={'b': 'bar'})
    app.cli.main(obj=info)

方案2:自定义上下文设置(贴近原生 Click 风格)

通过指定命令组的 context_settings,可以保持原生 Click 的字典式上下文用法,同时兼容 Flask CLI:

import flask
import click

app = flask.Flask(__name__)

# 自定义上下文设置,指定默认 obj 为字典
CONTEXT_SETTINGS = dict(obj=dict())

@app.cli.group(context_settings=CONTEXT_SETTINGS)
@click.option('-x', default='xx', help="set x")
@click.option('-y', default='yy', help="set y")
@click.pass_context
def cli(ctx, x, y):
    ctx.obj.update({'x': x, 'y': y})

@cli.command()
@click.pass_context
def foo(ctx):
    print(ctx.obj.get('x'))
    print(ctx.obj.get('b'))

if __name__ == "__main__":
    # 启动时传入自定义参数
    app.cli.main(obj={'b': 'bar'})

注意事项

  • 不要直接修改 ctx.obj 的类型,否则会破坏 Flask CLI 的内部逻辑
  • 通过 flask 命令行工具运行时,建议通过环境变量或配置文件传递参数,而非代码硬编码
  • 若需在命令中访问 Flask 应用实例,可直接通过 ctx.obj.app 获取

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 17:05:19