Flask入门:flask run运行入口函数

背景:

这两天在看后端代码覆盖率平台代码的时候,发现启动服务只需要执行flask run命令即可。但是找了半天都没有看到工程中Flask app实例对象是在哪里创建的。工程中定义了一个create_app()函数,可是没有看到调用它的地方。带着疑惑,尝试在工程中create_app()函数主动raise一个异常,来看看flask run从入口函数是怎么运行到create_app(),是如何调用create_app()函数的。

1、在命令行中执行flask启动命令flask run,其内部执行的是工程名\venv\Lib\site-packages\flask\cli.py 中的入口函数:

python 复制代码
def main() -> None:
    if int(click.__version__[0]) < 8:
        warnings.warn(
            "Using the `flask` cli with Click 7 is deprecated and"
            " will not be supported starting with Flask 2.1."
            " Please upgrade to Click 8 as soon as possible.",
            DeprecationWarning,
        )
    # TODO omit sys.argv once https://github.com/pallets/click/issues/536 is fixed
    cli.main(args=sys.argv[1:])


if __name__ == "__main__":
    main()

可以看到,主要的逻辑是在cli.main()函数中。

2、cli.main()函数

python 复制代码
    def main(self, *args, **kwargs):
        # Set a global flag that indicates that we were invoked from the
        # command line interface. This is detected by Flask.run to make the
        # call into a no-op. This is necessary to avoid ugly errors when the
        # script that is loaded here also attempts to start a server.
        os.environ["FLASK_RUN_FROM_CLI"] = "true"

        if get_load_dotenv(self.load_dotenv):
            load_dotenv()

        obj = kwargs.get("obj")

        if obj is None:
            obj = ScriptInfo(
                create_app=self.create_app, set_debug_flag=self.set_debug_flag
            )

        kwargs["obj"] = obj
        kwargs.setdefault("auto_envvar_prefix", "FLASK")
        return super().main(*args, **kwargs)

其中在load_dotenv()函数中加载工程下的".env"或".flaskenv"文件进行设置环境变量。.flaskenv文件的内容可以如下:

bash 复制代码
FLASK_APP=coverage_statistics

# 默认环境变量设置为development
FLASK_ENV=development
# FLASK_ENV=production
# FLASK_DEBUG = True

3、接着调用super.main()

...中间省略很多步

n、调用find_best_app() 该函数根据给定的模块名称,尝试在该模块中找到一个最有可能的应用,没有找到就会报错。

python 复制代码
def find_best_app(script_info, module):
    """Given a module instance this tries to find the best possible
    application in the module or raises an exception.
    """
    from . import Flask

    # Search for the most common names first.
    for attr_name in ("app", "application"):
        app = getattr(module, attr_name, None)

        if isinstance(app, Flask):
            return app

    # Otherwise find the only object that is a Flask instance.
    matches = [v for v in module.__dict__.values() if isinstance(v, Flask)]

    if len(matches) == 1:
        return matches[0]
    elif len(matches) > 1:
        raise NoAppException(
            "Detected multiple Flask applications in module"
            f" {module.__name__!r}. Use 'FLASK_APP={module.__name__}:name'"
            f" to specify the correct one."
        )

    # Search for app factory functions.
    for attr_name in ("create_app", "make_app"):
        app_factory = getattr(module, attr_name, None)

        if inspect.isfunction(app_factory):
            try:
                app = call_factory(script_info, app_factory)

                if isinstance(app, Flask):
                    return app
            except TypeError as e:
                if not _called_with_wrong_args(app_factory):
                    raise

                raise NoAppException(
                    f"Detected factory {attr_name!r} in module {module.__name__!r},"
                    " but could not call it without arguments. Use"
                    f" \"FLASK_APP='{module.__name__}:{attr_name}(args)'\""
                    " to specify arguments."
                ) from e

    raise NoAppException(
        "Failed to find Flask application or factory in module"
        f" {module.__name__!r}. Use 'FLASK_APP={module.__name__}:name'"
        " to specify one."
    )

1、先尝试在模块中查找是否有app或application名称的文件,没有则进入第二步;

2、然后查找模块中是否有Flask实例的属性对象,有一个则表明找到了,有多个则报错,没有则进入第三步;

3、查找是否有app工程方法"create_app"或"make_app",如果存在,则调用该工程方法创建app实例并返回,如果没有,则报错。

至此,终于知道Flask app对象是怎么创建,在哪里创建的了。

相关推荐
网安墨雨4 分钟前
Python自动化一------pytes与allure结合生成测试报告
开发语言·自动化测试·软件测试·python·职场和发展·自动化
powerfulhell12 分钟前
寒假python作业5
java·前端·python
铉铉这波能秀19 分钟前
LeetCode Hot100 中 enumerate 函数的妙用(2026.2月版)
数据结构·python·算法·leetcode·职场和发展·开发
毕设源码-赖学姐21 分钟前
【开题答辩全过程】以 基于python的电影推荐系统为例,包含答辩的问题和答案
开发语言·python
敲键盘的生活23 分钟前
MoneyPrinter重构之一:用nicegui调用大模型生成视频文案
python·重构·aigc·ai编程·ai写作
qq_2975746723 分钟前
【实战】POI 实现 Excel 多级表头导出(含合并单元格完整方案)
java·spring boot·后端·excel
小邓睡不饱耶25 分钟前
2026 CSDN榜单封神!3大热门技术+5个大厂案例,新手也能直接抄作业
python·ai
南极星100529 分钟前
我的创作纪念日--128天
java·python·opencv·职场和发展
码界筑梦坊30 分钟前
327-基于Django的兰州空气质量大数据可视化分析系统
python·信息可视化·数据分析·django·毕业设计·数据可视化
Highcharts.js31 分钟前
如何使用Highcharts SVG渲染器?
开发语言·javascript·python·svg·highcharts·渲染器