Flask应用实战经验总结:使用工厂函数创建app与uWSGI服务部署启动失败解决方案

news/2025/2/24 10:30:42/文章来源:https://www.cnblogs.com/xh2023/p/18733493

在 Flask 应用开发中,使用工厂函数创建应用实例,并借助 uWSGI 服务进行部署,是常见且高效的组合。

然而,在实际操作过程中,uWSGI 配置文件与应用启动函数之间的关系复杂,容易引发各种问题。

本文将详细探讨其中的关键要点和注意事项,帮助开发者顺利完成 Flask 应用的部署。

一、Flask 应用工厂函数简介

Flask 应用工厂函数是一种创建 Flask 应用实例的设计模式。通过将应用的创建逻辑封装在函数中,我们可以实现更灵活的配置和复用。例如:

from flask import Flask# 创建Flask应用
def create_app():app = Flask(__name__)# 加载配置app.config.from_object('config.Config')# 初始化扩展from models import dbdb.init_app(app)# 注册蓝图from api import register_blueprintsregister_blueprints(app)@app.route('/')def index():return "Hello, Flask!"return appif __name__ == '__main__':app = create_app()app.run()

 

在上述代码中,create_app函数负责创建 Flask 应用实例,配置应用,初始化数据库,并注册蓝图。这种方式使得应用的创建和配置分离,便于管理和维护。

二、uWSGI 配置文件详解

uWSGI 是一个高性能的 Web 服务器,支持多种协议和功能。在部署 Flask 应用时,需要正确配置 uWSGI 配置文件(通常为.ini格式)。以下是一个典型的 uWSGI 配置文件示例:

[uwsgi]
# 项目根目录
chdir = /home/flask_pro
# 应用模块和可调用对象
module = app:create_app
callable = app
# 进程和线程设置
master = true
processes = 4
threads = 2
# 网络设置
socket = 127.0.0.1:5000
# 其他设置
vacuum = true
harakiri = 60
pidfile = uwsgi.pid
daemonize = uwsgi.log
  1. chdir:指定项目的根目录,uWSGI 会在该目录下查找应用模块。
  2. module:指定要加载的应用模块和可调用对象。格式为<模块名>:<可调用对象>,这里的app是包含create_app函数的 Python 模块名,create_app是创建 Flask 应用实例的函数。
  3. callable:指定module中返回的可调用对象,即 Flask 应用实例。在上述示例中,create_app函数返回的 Flask 应用实例名为app
  4. master:设置为true时,uWSGI 会启动一个主进程来管理子进程,提高稳定性。
  5. processesthreads:分别设置 uWSGI 的进程数和每个进程的线程数,用于控制应用的并发处理能力。
  6. socket:指定 uWSGI 监听的 IP 地址和端口号,用于接收外部请求。
  7. vacuum:设置为true时,uWSGI 在退出时会自动清理环境,如删除临时文件。
  8. harakiri:设置请求的超时时间,单位为秒。
  9. pidfiledaemonize:分别指定 uWSGI 进程 ID 文件和日志文件的路径,用于记录进程信息和日志。

三、uWSGI 配置文件与 app 启动函数的关系

  1. 入口函数的匹配:uWSGI 通过modulecallable配置来定位 Flask 应用的入口函数。module指定包含应用创建逻辑的模块,callable指定模块中返回 Flask 应用实例的函数或对象。在使用工厂函数创建应用时,callable通常是工厂函数返回的应用实例。
  2. 参数传递问题:在配置 uWSGI 时,容易混淆应用创建函数和 WSGI 应用接口。WSGI 规范要求应用入口函数接受environstart_response两个参数,但 Flask 应用工厂函数通常不需要这两个参数。如果在工厂函数中错误地添加了这两个参数,可能会导致 “TypeError: 'Flask' object is not iterable” 错误。因为工厂函数返回的 Flask 应用实例本身不是可迭代的,而 WSGI 期望的是一个可迭代对象来生成响应内容。正确的做法是,在工厂函数中返回 Flask 应用实例,然后通过 uWSGI 的配置来正确调用应用。
  3. 应用配置与环境变量:uWSGI 配置文件中的chdir和 Flask 应用工厂函数中的配置加载逻辑密切相关。chdir指定的项目根目录决定了 Flask 应用查找配置文件、静态文件和模板文件的路径。在工厂函数中,通常会使用app.config.from_object方法加载配置,配置文件的路径和名称应与项目结构和 uWSGI 配置相匹配。此外,还可以通过环境变量来传递配置信息,提高应用的灵活性和可扩展性。

四、部署过程中的问题及解决方法

通常根据网上经验,按照根据上面的app代码和uWSGI配置文件部署应该没有问题,但是实际部署到服务器上,启动后发现app并没有正确启动成功,日志显示报错如下:

错误信息 “TypeError: create_app() takes 0 positional arguments but 2 were given”

表示 create_app() 函数被调用时传入了两个位置参数,但该函数不接受任何位置参数。

在 uWSGI 中,如果 callable 参数指定的函数不接受任何参数,那么在配置文件中就不应该提供任何额外的参数。

uWSGI 默认会将 environ 和 start_response 两个参数传递给 WSGI 应用程序。这可能是导致错误的原因。

[INFO] bound built-in connection pool when new client. maxsize=10,10
WSGI app 0 (mountpoint='') ready in 4 seconds on interpreter 0x26ced20 pid: 3592 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 3592)
spawned uWSGI worker 1 (pid: 3595, cores: 2)
spawned uWSGI worker 2 (pid: 3596, cores: 2)
spawned uWSGI worker 3 (pid: 3597, cores: 2)
spawned uWSGI worker 4 (pid: 3598, cores: 2)
TypeError: create_app() takes 0 positional arguments but 2 were given


然而不是随便将将 environ 和 start_response 两个参数加入到create_app(environ,start_response)函数中的,这样修改,使用uWSGI启动后,又会出现新的报错:

“TypeError: 'Flask' object is not iterable” 错误。

因为工厂函数返回的 Flask 应用实例本身不是可迭代的,而 WSGI 期望的是一个可迭代对象来生成响应内容。

经过查询网上资料以及多个AI平台分析问题,多次测试验证,最终解决方案如下:

 

1、修改flask应用启动代码:

  增加一个符合 WSGI 规范的应用入口函数。

from flask import Flask# 创建Flask应用
def create_app():print("开始创建Flask应用...")app = Flask(__name__)# 加载配置app.config.from_object('config.Config')# 初始化扩展from models import dbdb.init_app(app)# 注册蓝图from api import register_blueprintsregister_blueprints(app)@app.route('/')def index():return "Hello, Flask!"return app# 定义一个符合 WSGI 规范的应用入口函数
def application(environ, start_response):app = create_app()return app.wsgi_app(environ, start_response)if __name__ == '__main__':app = create_app()app.run()

 

2、修改uWSGI 配置文件:

  修改 module:指定要加载的应用模块和可调用对象。格式为<模块名>:<可调用对象>。

  修改 callable:指定module中返回的可调用对象。

[uwsgi]
# 这里是你的项目根目录路径
chdir = /home/项目根目录路径
# 模块名,这里用 app;app:application 是指定一个 Python 的可执行文件,它包括符合 WSGI 规范的代码
module = app:application
# 因为 application 是启动整个服务的入口,所以是 application
callable = application
# ... 其他配置不变 ...

 

3、使用uWSGI启动app:

[INFO] generate built-in connection pool success. maxsize=10,10
[INFO] bound built-in connection pool when new client. maxsize=10,10
[INFO] bound built-in connection pool when new client. maxsize=10,10
[INFO] bound built-in connection pool when new client. maxsize=10,10
[INFO] bound built-in connection pool when new client. maxsize=10,10
[INFO] bound built-in connection pool when new client. maxsize=10,10
WSGI app 0 (mountpoint='') ready in 1 seconds on interpreter 0x2656cf0 pid: 3772 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 3772)
spawned uWSGI worker 1 (pid: 3775, cores: 2)
spawned uWSGI worker 2 (pid: 3776, cores: 2)
spawned uWSGI worker 3 (pid: 3777, cores: 2)
spawned uWSGI worker 4 (pid: 3778, cores: 2)
开始创建Flask应用...

 启动成功,打开网址验证下你的服务接口。

五、总结

在 Flask 应用开发中,使用工厂函数创建应用实例并结合 uWSGI 进行部署,可以提高应用的灵活性、可维护性和性能。

在配置 uWSGI 时,需要特别注意配置文件与应用启动函数之间的关系,确保正确指定应用入口函数、处理参数传递问题,并合理设置进程、线程和网络参数。

同时,通过查看日志和解决常见问题,可以快速完成应用的部署和调试。希望本文对您在 Flask 应用部署方面有所帮助,祝您开发顺利!

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/888916.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vite build 打包的文件取消hash码

build: {rollupOptions: {output: {entryFileNames: `assets/[name].js`, // 打包后的入口文件名chunkFileNames: `assets/[name].js`, // 打包后的代码块文件名assetFileNames: `assets/[name].[ext]`, // 打包后的静态资源文件名},},},增加这段代码即可,加的位置需要注意。

再战博客园美化(真正的五)——实际发布

25-02-24 补充 这一篇偶然在我的草稿箱里面被发现。 也就是说,从五开始,少了一篇,而我却没有发现 迭代太快了。 以下是原始文章我不免想到一个问题——如果我弄了这么多以后,发现根本不能用,那咋办? 所以我必须先尝试发布一次,得在博客园上实际看到效果。有一个文件上MB…

【草稿】图片上传2

本随笔用于上传图片 博客园居然不压缩图片,有点太良心了,我还得手动去压缩一遍。

word

选项卡的折叠和固定功能区快捷键:Ctrl+F1后退一步和前进一步的快捷键分别是:Ctrl+z、Ctrl+y页面放大和缩小命令:按住Ctrl,滚动鼠标滚轮,点击右下角的百分比,弹出显示比例对话框,可以选择一个比例,点击确定也可以实现,如下图:新建word命令,可以页面右击新建,也可以在…

idea连接sqlserver出现[08S01] 驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接错误(转)

错误信息 选择对应的DataSource 修改两个地方即可 修改Advanced页签的trustServerCertificate 在使用 JDBC 连接 SQL Server 数据库时,trustServerCertificate 是一个连接参数,用于指示客户端是否信任服务器端的证书。当 trustServerCertificate 参数设置为 true 时,客…

2025/2/23 LeetCode151. 反转字符串中的单词

151. 反转字符串中的单词 - 力扣(LeetCode) 之前做的2024/12/14 【字符串】LeetCode151.反转字符串中的单词 【√】知识点:几个易错点,split函数 - axuu - 博客园 这些函数又忘了。 总结split(): 拆分字符串为列表。strip(): 去除字符串两端的空白字符。[::-1]: 反转字符…

谷歌逐步淘汰V2插件,广告拦截不能用了?

本文是《最全面的浏览器教程》第九篇,介绍目前扩展生态的问题。​ 你的浏览器扩展可能一夜之间失效!快收下这份自救指南。 本文是《最全面的浏览器教程》第九篇,介绍目前扩展生态的问题。 ‍ 起因 Chrome Manifest v2 是 Chrome 扩展程序的一种配置文件格式,是扩展的一部分…

2024CISCN长城杯wp

威胁检测与网络流量分析 zeroshell_1 1.解法一:分析流量包 ,提取http对象,找到包含命令的流量包Referer字段很像base64编码,试一试 真是flag2.解法二:CTF_NAT一把梭,找到包含flag的密文,cyberchef解密zeroshell_2 1.解法一:网上找漏洞payload,在url里进行注入,先找fl…

Debian 11 离线安装MySql记录

环境:mysql:mysql-8.0.32-linux-glibc2.17-aarch64.tar.gz 1、上传到服务器,然后解压缩 tar -zxvf mysql-8.0.32-linux-glibc2.17-aarch64.tar.gz 2、移动到指定目录/usr/local/mysql-8 mv mysql-8.0.32-linux-glibc2.17-aarch64 /usr/local/mysql-8 3、创建MySQL数据目录 m…

一个支持多家云存储驱动的公有云文件系统!

Cloudreve —— 一个基于 Go + React 实现的支持多家云存储驱动的公有云文件系统,适用于搭建个人网盘、文件分享系统等。大家好,我是 Java陈序员。 在日常生活中,我们会记录很多精彩的瞬间,或图片或视频,并存放在网盘中。 然而,很多商业网盘下载速度慢,而且不能很好地保…

传统ftp软件问题频出,一文了解适配的替代方案!

在互联网发展的早期,ftp软件凭借其简单易用的特性,成为了文件传输领域的中流砥柱,帮助无数企业实现文件的远程传输与共享。时过境迁,在如今数据量呈爆炸式增长、网络环境愈发复杂的时代,ftp软件就像一位上了年纪的老将,逐渐显露出诸多力不从心之处。 1.数据裸奔的安全风…