Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
Heroku 上 Flask API 与 Dash 应用的部署与集成_创想鸟

Heroku 上 Flask API 与 Dash 应用的部署与集成

Heroku 上 Flask API 与 Dash 应用的部署与集成

本文探讨了在 Heroku 部署 Flask API 与 Dash 应用时常见的 405 Method Not Allowed 错误及其解决方案。核心问题在于 Heroku 的 Procfile 配置与 Flask 和 Dash 应用实例的交互方式。通过将 Dash 应用集成到主 Flask 实例中,并正确配置 Procfile 指向单一的 Flask 应用入口,可以有效解决路由冲突,实现 API 和 UI 的协同工作。教程将提供集成示例代码,并强调部署注意事项。

1. 背景与问题描述

在 heroku 平台部署 web 应用时,开发者常遇到将后端 api(如使用 flask 构建)与前端交互式界面(如使用 dash 构建)结合的需求。一个典型的场景是,flask api 负责数据接收和处理(例如,将远程数据写入 postgresql 数据库),而 dash 应用则提供数据可视化或管理界面。然而,当尝试在同一个 heroku 应用中同时运行这两个组件时,可能会遭遇 405 method not allowed 错误,尤其是在尝试向 flask api 端点发送 post 请求时。

原始问题中的错误信息 response content: b’a style=”color:#f60; text-decoration:underline;” title= “html”href=”https://www.php.cn/zt/15763.html” target=”_blank”>html>nn

405 Method Not Allowedn

Method Not Allowed

n

The method is not allowed for the requested URL.

n’ 明确指出服务器不接受对指定 URL 使用请求的方法(POST)。这通常不是认证问题,而是路由或服务器配置问题。

2. 深入理解问题根源:Flask、Dash 与 Heroku Procfile

问题的核心在于 Flask 和 Dash 应用实例的独立性以及 Heroku Procfile 的工作方式。

在提供的代码中,存在两个独立的应用程序实例:

app = Flask(__name__):这是一个标准的 Flask 应用实例,用于定义 API 路由(例如 /ingest)。dash_app = dash.Dash(__name__,):这是一个 Dash 应用实例,它内部也运行着一个 Flask 服务器 (dash_app.server)。

当在 Procfile 中定义 Heroku 的 Web 进程时,我们必须指定一个单一的入口点供 Gunicorn(Heroku 推荐的 WSGI HTTP 服务器)启动。

如果 Procfile 指向 your_module_name:app,Gunicorn 将启动 app = Flask(__name__) 实例。此时,@app.route 定义的 API 路由将可用,但 dash_app 及其路由将无法访问。如果 Procfile 指向 your_module_name:server(这里的 server 通常指 dash_app.server),Gunicorn 将启动 Dash 应用内部的 Flask 实例。此时,Dash 界面将可用,但 app = Flask(__name__) 实例上定义的 API 路由将无法访问,从而导致 405 Method Not Allowed 错误,因为 /ingest 路径对于 Dash 应用的内部 Flask 实例而言可能不存在或不允许 POST 方法。

简而言之,尝试在同一个 Heroku dyno 中通过单一 Procfile 入口同时运行两个独立的 Flask/Dash 实例是行不通的。

3. 解决方案:将 Dash 应用集成到现有 Flask 应用中

最推荐且最健壮的解决方案是将 Dash 应用作为子应用集成到主 Flask 应用中。这样,所有路由(无论是 Flask API 路由还是 Dash UI 路由)都将由同一个 Flask 服务器实例处理。

3.1 修正后的应用代码

以下是整合了 Flask API 和 Dash UI 的 Python 应用代码示例:

from flask import Flask, request, jsonify, make_responsefrom flask_cors import CORSimport dashfrom dash import dcc, html, Input, Outputimport jsonimport os # 用于获取数据库连接字符串# 1. 创建主 Flask 应用实例app = Flask(__name__)CORS(app) # 为主 Flask 应用启用 CORS# 2. 将 Dash 应用集成到现有的 Flask 应用中# 通过 server=app 参数,Dash 会使用我们已经创建的 Flask 应用实例# url_base_pathname 可以指定 Dash 应用的根路径,例如 /dashboard/dash_app = dash.Dash(__name__, server=app, url_base_pathname='/dashboard/')# 3. 定义 Flask API 路由# 这个路由现在属于主 Flask 应用@app.route('/ingest', methods=['OPTIONS', 'POST'])def handle_ingest():    # 处理 CORS 预检请求    if request.method == 'OPTIONS':        response = make_response()        response.headers.add('Access-Control-Allow-Origin', '*') # 生产环境请指定具体域名        response.headers.add('Access-Control-Allow-Headers', 'Authorization, Content-Type')        response.headers.add('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')        return response    # 认证逻辑    token = request.headers.get('Authorization')    # 客户端发送的是 'Bearer too_many_secrets',所以这里也要匹配    valid_tokens = ["Bearer too_many_secrets"]     if token in valid_tokens:        data = request.json # 假设数据以 JSON 格式发送        # --- 在这里执行数据验证和写入 PostgreSQL 数据库的逻辑 ---        # 示例:连接到 Heroku Postgres 数据库并插入数据        # import psycopg2        # DATABASE_URL = os.environ.get('DATABASE_URL') # Heroku 会自动提供        # try:        #     conn = psycopg2.connect(DATABASE_URL, sslmode='require')        #     cur = conn.cursor()        #     # 示例:创建一个表并插入数据        #     # cur.execute("CREATE TABLE IF NOT EXISTS sensor_data (id SERIAL PRIMARY KEY, sensor TEXT, value REAL, timestamp TIMESTAMPTZ DEFAULT NOW());")        #     # cur.execute("INSERT INTO sensor_data (sensor, value) VALUES (%s, %s);", (data.get('sensor'), data.get('value')))        #     conn.commit()        #     cur.close()        #     conn.close()        #     print(f"Data ingested successfully: {data}")        #     return jsonify({"message": "Data ingested successfully", "received_data": data}), 200        # except Exception as e:        #     print(f"Database error: {e}")        #     return jsonify({"message": "Failed to ingest data due to database error"}), 500        # 仅为演示,实际应写入数据库        print(f"Success: Data ingested successfully: {data}")        return jsonify({"message": "Data ingested successfully", "received_data": data}), 200    else:        print("Unauthorized user: Your token was Invalid")        return jsonify({"message": "Unauthorized"}), 401# 4. 定义 Dash 应用的布局和回调# Dash 应用现在是主 Flask 应用的一个部分dash_app.layout = html.Div(children=[    html.H1(children='Heroku 集成应用'),    html.P('欢迎来到 Dash 仪表板!'),    dcc.Link('访问数据摄取 API 端点', href='/ingest', refresh=True), # 链接到 Flask API    html.Div(id='output-message', style={'margin-top': '20px'})])# 示例 Dash 回调 (如果需要)# @dash_app.callback(#     Output('output-message', 'children'),#     Input('url', 'pathname') # 需要 dcc.Location 组件才能获取 pathname# )# def display_page(pathname):#     if pathname == '/dashboard/':#         return html.Div("您正在查看 Dash 仪表板首页。")#     elif pathname == '/ingest':#         return html.Div("您已点击了 API 端点链接,但此页面本身不提供交互。")#     return html.Div("未知页面")# 5. 主程序入口if __name__ == '__main__':    # 在本地运行,Flask 应用将作为主服务器    app.run(debug=True)

3.2 客户端请求脚本

客户端请求脚本保持不变,因为它只需知道 API 端点。

import requestsdata = {    "sensor": "temperature",    "value": 25.5}# 假设 Heroku 应用的 URL 是 'https://my_app.herokuapp.com/'# API 端点现在是 '/ingest'api_endpoint = 'https://my_app.herokuapp.com/ingest'  token = 'too_many_secrets' # 客户端的原始 tokenheaders = {'Authorization': f'Bearer {token}'} # 按照约定发送 Bearer tokenresponse = requests.post(api_endpoint, json=data, headers=headers, verify=True)if response.status_code == 200:    print("Data sent successfully")    print(f"Response: {response.json()}")else:    print(f"Failed to send data. Status code: {response.status_code}")    print(f'Response content: {response.content.decode()}') # 解码以便阅读

3.3 Heroku Procfile 配置

由于我们将 Dash 集成到了主 Flask 应用 app 中,现在只需要 Procfile 指向这个主 Flask 应用实例。假设你的 Python 文件名为 app.py:

web: gunicorn app:app

这里的 app:app 表示:

app (第一个):指的是你的 Python 模块文件名(例如 app.py)。app (第二个):指的是该模块中 Gunicorn 应该启动的 Flask 应用程序实例的变量名 (app = Flask(__name__))。

4. 部署注意事项

依赖管理: 确保 requirements.txt 文件中包含了所有必要的库,例如 flask, dash, dash-core-components, dash-html-components, flask-cors, gunicorn, psycopg2 (如果使用 PostgreSQL)。环境变量: 对于敏感信息(如数据库连接字符串、API 密钥),应使用 Heroku 环境变量而非硬编码。例如,Heroku 会自动为 Heroku Postgres 数据库提供 DATABASE_URL 环境变量。CORS 配置: 在生产环境中,Access-Control-Allow-Origin: ‘*’ 应该被替换为你的前端应用或客户端的特定域名,以增强安全性。授权令牌: 确保客户端发送的授权令牌格式(例如 Bearer )与服务器端验证的格式一致。Gunicorn 配置: 如果需要更高级的 Gunicorn 配置(例如工作进程数量、超时时间),可以在 Procfile 中添加参数或创建 gunicorn.conf.py 文件。数据库连接: 在 Heroku 上连接 PostgreSQL 数据库时,通常需要 psycopg2-binary 库,并且连接字符串(DATABASE_URL)会自动注入到环境中。

5. 总结

通过将 Dash 应用作为子应用集成到主 Flask 应用中,并确保 Procfile 正确指向这个统一的 Flask 实例,我们能够成功地在 Heroku 上部署一个同时提供 API 服务和交互式 UI 的应用。这种方法避免了多个应用实例之间的冲突,简化了部署和管理,并解决了 405 Method Not Allowed 这一常见的部署问题。理解 Heroku Procfile 与应用实例的对应关系是成功部署此类复杂应用的关键。

以上就是Heroku 上 Flask API 与 Dash 应用的部署与集成的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1373663.html

赞 (0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
使用 Pandas 将数值数据分配到分类区间
上一篇 2025年12月14日 13:27:36
Python Pandas数据分箱:处理年龄分类与非数值数据
下一篇 2025年12月14日 13:27:47

相关推荐

  • X 旗下 Grok 推出即时语音搜索功能 向 Google 发起挑战?

    近日,X 平台的人工智能助手 Grok 正式上线“即时语音搜索”功能,用户现在可通过语音直接提问,触发实时网络检索,并迅速获得整合后的精准答复。这项新能力意在优化信息查询流程,推动人机互动向更自然、高效的形态发展。 根据官方说明与实际用户体验,Grok 的语音搜索实现了“说话即搜、即时回应”的流畅体…

    2026年9月23日
    100
  • Java JUnit assertThrows 与异常消息比对:避免常见陷阱

    本教程深入探讨在 Java JUnit 中使用 assertThrows 进行异常测试时常见的 assertEquals 误用问题。它详细解释了为何不能直接将期望的字符串消息与捕获到的异常对象进行比对,并提供了正确的解决方案:通过 e.getMessage() 获取异常消息进行精确断言,确保测试的准…

    2026年9月23日
    000
  • PHP:根据条件动态禁用表格中的按钮

    本文旨在解决在PHP中,根据表格行中两列的值是否相等,动态禁用对应按钮的问题。通过修改循环遍历数据并生成HTML表格的代码,在生成按钮时增加条件判断,实现当mi_name列和item_name列的值相等时,禁用该行的按钮。文章提供两种实现方式,并附带代码示例,帮助开发者快速实现此功能。 在PHP中动…

    2026年9月23日
    100
  • safari浏览器如何导入Netscape格式的书签文件_safari浏览器导入Netscape书签方法

    Safari无法直接读取Netscape格式书签时,可通过HTML文件转换、第三方工具修复或借助Chrome/Firefox中转导入。首先确认书签文件含标准结构,尝试直接导入Safari;若失败,使用Linkman Lite等工具修复格式后导入;或通过Chrome先行导入再导出标准HTML文件,最后…

    2026年9月23日
    000
  • VSCode如何通过AI优化内存使用 VSCode智能内存分析调试插件

    ai并不能直接优化vscode的内存占用,而是通过赋能智能化的内存分析调试插件,间接提升vscode的运行效率和开发体验;2. 这类插件通过采集堆快照、cpu性能数据、gc日志和扩展资源消耗等运行时信息,结合ai的模式识别与异常检测能力,精准识别内存泄漏、未清理的事件监听器、循环引用等问题;3. a…

    2026年9月23日
    200
  • PHP容器与依赖注入怎么理解_PHP中DI容器概念与Pimple等库应用

    依赖注入通过外部传入依赖解耦代码,容器如Pimple集中管理对象创建与依赖解析,提升可测试性与维护性,适用于中小型项目。 PHP中的容器和依赖注入(Dependency Injection,简称DI)是现代开发中解耦代码、提升可测试性和可维护性的核心技术。理解它们的关键在于掌握“控制反转”(Inve…

    2026年9月23日
    100
  • 悟空浏览器提示“网络错误”无法上网怎么办_悟空浏览器网络错误解决方法

    首先检查网络连接是否正常,确认Wi-Fi或移动数据已开启并信号良好;尝试切换网络类型或重启路由器。若问题仍存在,进入设置清除悟空浏览器缓存与数据,排除因缓存堆积导致的加载失败。接着可更改DNS为8.8.8.8和114.114.114.114以提升解析成功率。同时禁用浏览器插件与扩展功能,避免其干扰网…

    2026年9月23日
    100
  • VS Code算法实战:竞赛编程与调试环境搭建

    首先安装编程语言环境及VS Code扩展,如C/C++、Code Runner和LeetCode;接着配置Code Runner支持编译运行与输入重定向;最后通过代码片段提升编码速度,形成高效竞赛开发环境。 在竞赛编程中,高效的开发环境能大幅提升编码速度与调试效率。VS Code凭借轻量、可扩展和强…

    2026年9月23日
    000
  • 字节入局,AR眼镜掀起新“风口”?

    近日,关于老凤祥与字节跳动合作推出AI眼镜的消息在网络上引发热议。据相关媒体报道,老凤祥计划联合字节跳动旗下的火山引擎共同开发多款AI眼镜,并由豆包大模型提供技术支持,预计将在今年7月正式发布。 对此,6月12日,火山引擎方面进行了澄清。其负责人表示,并未有与老凤祥合作研发AI智能眼镜的计划。而豆包…

    2026年9月23日
    000
  • VSCode如何设置代码自动补全触发 VSCode智能提示触发条件的优化

    要解决vscode代码自动补全的触发、准确性、禁用和速度问题,需按以下步骤操作:1. 调整editor.quicksuggestions控制提示触发条件,如设置”other”: true, “comments”: false, “strin…

    2026年9月23日
    200
  • 在无Maven或Eclipse环境下手动构建Java Web应用WAR包的教程

    本教程详细介绍了如何在不依赖Maven或Eclipse等集成开发环境的情况下,为Java Web应用程序手动生成WAR(Web Application Archive)文件。文章首先阐述了WAR文件的基本结构,随后通过一个Ant构建脚本的实例,指导读者完成从源代码编译、文件组织到最终WAR包生成的全…

    2026年9月23日
    000
  • 如何授予MySQL用户特定权限?

    如何授予MySQL用户特定权限?如何授予MySQL用户特定权限?如何授予MySQL用户特定权限?如何授予MySQL用户特定权限?

    要授予mysql用户特定权限,需使用grant语句并遵循最小权限原则。1. 登录mysql,使用root或有grant权限的账户;2. 使用grant 权限 on 数据库名.表名 to ‘用户名’@’主机名’语法授予权限,如select、insert等…

    2026年9月23日 • 用户投稿
    000
  • AdobePhotoshop的AI混合工具怎么用?掌握智能图像编辑的教程

    Photoshop的AI混合工具以生成式填充和神经网络滤镜为代表,通过语义理解实现智能图像融合。生成式填充可依据文本提示添加、移除或扩展内容,自动匹配光影与纹理;神经网络滤镜如和谐化则优化颜色与光照匹配。与传统基于像素计算的混合模式不同,AI工具理解图像内容,实现“生成并融合”。使用时需精准输入英文…

    2026年9月23日
    100
  • PHP多维数组重构:按指定键值分组数据

    本文将详细介绍如何在PHP中将扁平化的关联数组列表重构为多维数组,核心思路是根据数组中某个特定键(例如 object_type)的值进行分组,将具有相同键值的所有子数组归集到同一个父级键下,从而实现数据的层次化组织,提高数据的可读性和管理效率。 引言:数据重构的需求 在PHP开发中,我们经常会遇到需…

    2026年9月23日
    000
  • 解决 Conda 环境中 Java 版本冲突的策略

    本文旨在解决 Conda 环境中 Java 版本激活不正确的问题。当用户尝试在 Conda 环境中指定特定 Java 版本(如 OpenJDK 8)时,系统可能仍激活旧的或错误的 Java 版本。教程将详细分析问题根源,并提供一种通过精确指定 Java 包名来确保 Conda 环境正确管理 Java…

    2026年9月23日
    000
  • Django 项目运行时遇到“django.core.exceptions.ImproperlyConfigured”错误,如何解决?

    当在运行 Django 项目时遇到“django.core.exceptions.ImproperlyConfigured”错误时,这表明 Django 无法导入其预期的数据库后端。 在给定的代码中,错误消息指出 Django 无法导入“django.db.backends.mysql”,这可能是因…

    2026年9月23日
    000
  • Windows安装过程中蓝屏INACCESSIBLE_BOOT_DEVICE怎么办?

    1、蓝屏“INACCESSIBLE_BOOT_DEVICE”通常因SATA模式不匹配或驱动缺失导致;2、进入BIOS将SATA模式从RAID改为AHCI可解决兼容性问题;3、安装时加载主板存储控制器驱动以识别NVMe或RAID磁盘;4、使用diskpart命令清理磁盘并转换为GPT(UEFI)或MB…

    2026年9月23日
    000
  • 淘宝支付方式无法选择怎么办

    支付方式无法选择通常因账户设置、系统版本或商家限制;2. 关闭“优先使用支付宝”开关可恢复其他支付选项;3. 微信支付需绑定“零钱”而非“零钱通”;4. 预售、大额订单、跨境商品等可能仅支持特定支付方式;5. 更新App、重启设备或切换网络可解决加载失败问题。 淘宝支付方式无法选择,通常和账户设置、…

    2026年9月23日
    1000
  • 谷歌为 Gemini CLI 带来扩展功能

    谷歌旗下的 AI 编程助手 Gemini CLI 最近推出了名为“扩展”的全新功能。官方表示,这一更新让用户能够“接入常用工具,并定制属于自己的 AI 命令行体验”。现在,任何开发者都可以发布扩展程序,无需经过谷歌的审核批准即可上线使用。 目前扩展库中已提供超过 50 款扩展,涵盖多种实用场景。例如…

    2026年9月23日
    000
  • 如何恢复未保存的WPS格式文档_WPS未保存文档恢复操作技巧

    首先尝试WPS自动恢复功能,重新打开软件后查看“文档恢复”面板;若无效,可手动查找C:Users当前用户名AppDataLocalKingsoftWPS Officecache目录下的临时文件;若启用云端同步,可通过“备份与恢复”中的历史版本找回;还可使用系统搜索*.asd文件定位自动保存的副本。 …

    2026年9月23日
    100

发表回复

登录后才能评论
关注微信