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

Flask应用部署Heroku后无法更新CSV,求助写入GitHub托管CSV

解决Heroku上CSV无法持久化&向GitHub托管CSV追加内容的方案

首先,先解释你在Heroku上遇到的CSV不更新问题:Heroku使用临时文件系统(Ephemeral Filesystem),所有对本地文件的修改只在当前dyno的生命周期内有效——当dyno重启(比如部署更新、自动缩放、睡眠唤醒),这些修改就会丢失。而且多个dyno之间的文件系统是独立的,所以即使看起来运行正常,数据也不会持久化,这就是你克隆仓库看不到更新的原因。

接下来解决你现在的核心需求:向GitHub托管的CSV文件追加内容。GitHub本身不是数据库,但我们可以通过GitHub REST API来实现修改仓库里的CSV文件,具体步骤如下:

1. 准备GitHub Personal Access Token (PAT)

你需要生成一个带仓库权限的PAT,用来通过API修改你的仓库:

  • 登录GitHub,进入「Settings」→「Developer settings」→「Personal access tokens」
  • 点击「Generate new token」,勾选repo权限(需要完整的仓库读写权限)
  • 生成后复制保存好这个token(只显示一次)

2. 用Python实现追加功能

我们可以用requests库调用GitHub API,结合Pandas处理CSV格式,确保数据格式正确。

步骤说明:

  1. 调用API获取当前CSV文件的信息(包括唯一的sha值,GitHub需要它确认修改的是最新版本)
  2. 解码文件内容,用Pandas加载并追加新数据
  3. 将更新后的内容编码为base64(GitHub API要求的格式)
  4. 发送PUT请求更新文件

完整代码示例

import os
import requests
import pandas as pd
import base64
from io import StringIO

# 从环境变量获取token,避免硬编码(Heroku上用heroku config:set GITHUB_TOKEN=你的token设置)
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
REPO_OWNER = "parthpandyappp"
REPO_NAME = "Saturday-Talks"
FILE_PATH = "registered.csv"
API_URL = f"https://api.github.com/repos/{REPO_OWNER}/{REPO_NAME}/contents/{FILE_PATH}"

def append_name_to_github_csv(new_name):
    # 1. 获取当前CSV文件的元数据和内容
    headers = {"Authorization": f"token {GITHUB_TOKEN}"}
    try:
        response = requests.get(API_URL, headers=headers)
        response.raise_for_status()
        file_data = response.json()
    except requests.exceptions.RequestException as e:
        print(f"获取文件失败: {e}")
        return None

    # 2. 解码当前CSV内容并加载为DataFrame
    current_content = base64.b64decode(file_data["content"]).decode("utf-8")
    df = pd.read_csv(StringIO(current_content))

    # 3. 追加新名称(假设CSV的列名为"name",如果不是请修改)
    new_row = pd.DataFrame({"name": [new_name]})
    df = pd.concat([df, new_row], ignore_index=True)

    # 4. 将更新后的内容转为CSV字符串并编码为base64
    updated_csv = df.to_csv(index=False)
    updated_content_b64 = base64.b64encode(updated_csv.encode("utf-8")).decode("utf-8")

    # 5. 发送更新请求到GitHub API
    payload = {
        "message": f"Register new participant: {new_name}",
        "content": updated_content_b64,
        "sha": file_data["sha"]  # 必须传入当前文件的sha,否则会报错
    }

    try:
        update_response = requests.put(API_URL, json=payload, headers=headers)
        update_response.raise_for_status()
        print("名称追加成功!")
        return update_response.json()
    except requests.exceptions.RequestException as e:
        print(f"更新文件失败: {e}")
        return None

# 在Flask路由中调用这个函数
# @app.route("/submit", methods=["POST"])
# def submit_name():
#     name = request.form.get("name")
#     if name:
#         append_name_to_github_csv(name)
#         return "提交成功!"
#     return "请输入名称!"

3. 关键注意事项

  • 不要硬编码token:在Heroku上用heroku config:set GITHUB_TOKEN=你的PAT设置环境变量,代码里用os.getenv获取,避免泄露敏感信息
  • 处理并发冲突:如果多个用户同时提交,可能会出现409 Conflict错误(因为获取sha和更新之间文件被修改了),可以添加重试逻辑解决
  • GitHub API速率限制:免费用户每小时最多5000次请求,小应用完全足够,大流量场景建议改用数据库(比如Heroku Postgres)
  • CSV列名匹配:确保代码里的列名和你的registered.csv一致,如果你的CSV有多列,调整pd.DataFrame的字段即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 18:22:57