You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Discord机器人Heroku部署时无法写入JSON文件,如何实现写入本地文件?

解决Heroku上Discord机器人无法写入文件的问题

嘿,我来帮你搞定这个困扰!先把核心问题理清楚,再给你两个实用的解决方案——一个是适合长期用的生产级方案,另一个能满足你写入本地电脑文件的需求。

为什么Heroku上写本地文件会失效?

Heroku的文件系统是**临时(Ephemeral)**的,简单说就是:

  • 每次机器人重启、重新部署,或者Heroku自动切换实例时,所有本地修改的文件都会被重置回部署时的初始状态
  • 你写入的JSON文件看起来当时生效了,但只要机器人一重启,数据就全没了,这就是你遇到的问题根源

方案1:用数据库替代本地JSON文件(推荐!)

等级系统需要持久化存储数据,数据库才是靠谱的选择,比写文件稳定太多。这里给你两个常见的选项:

  • Heroku PostgreSQL:Heroku自带免费的PostgreSQL实例,配置起来很简单。你可以用psycopg2或者ORM工具(比如SQLAlchemy)来操作数据库,把用户等级数据存在数据表中,替代原来的JSON文件。
  • MongoDB Atlas:如果更习惯用类似JSON的NoSQL结构,可以用MongoDB的免费云服务,直接存文档格式的数据,和你原来的JSON逻辑衔接更顺畅。

举个简单思路:原来读写levels.json的代码,改成连接数据库,执行查询、插入或更新操作。比如用SQLAlchemy定义一个UserLevel模型,通过模型来管理用户等级数据,这样数据就会存在云端数据库里,不会丢失。

方案2:让机器人写入你本地电脑的文件

如果一定要把数据写到自己电脑的JSON文件里,得让云端的机器人能访问到你的本地文件系统——这需要你在本地搭一个简单的接口,把本地文件暴露给云端:

步骤1:在本地搭一个HTTP服务器

用Flask或者FastAPI写个轻量服务,提供一个接收数据的接口,收到数据后写入本地的JSON文件。比如Flask的示例代码:

from flask import Flask, request, jsonify
import json

app = Flask(__name__)
# 你的本地JSON文件路径
LEVELS_FILE = "./levels.json"

@app.route('/save-level', methods=['POST'])
def save_level():
    # 接收机器人传来的用户等级数据
    level_data = request.get_json()
    user_id = level_data.get("user_id")
    level = level_data.get("level")

    # 读取现有数据(文件不存在则新建)
    try:
        with open(LEVELS_FILE, 'r', encoding='utf-8') as f:
            data = json.load(f)
    except FileNotFoundError:
        data = {}

    # 更新用户等级数据
    data[str(user_id)] = level

    # 写回本地文件
    with open(LEVELS_FILE, 'w', encoding='utf-8') as f:
        json.dump(data, f, indent=2)

    return jsonify({"status": "success"})

if __name__ == '__main__':
    # 允许外部访问本地服务器
    app.run(host='0.0.0.0', port=5000)

步骤2:把本地服务器暴露到公网

Heroku的机器人在云端,没法直接访问你本地的服务器,所以需要用内网穿透工具(比如ngrok)把本地端口暴露出去:

  1. 下载ngrok后,运行命令:ngrok http 5000
  2. 运行后会得到一个公网URL,比如https://abc123.ngrok.io,这就是本地服务器的公网入口

步骤3:修改机器人代码,发送数据到本地接口

原来写JSON文件的地方,改成发送HTTP请求到刚才的ngrok URL:

import requests

def update_user_level(user_id, level):
    # 替换成你的ngrok公网URL
    api_url = "https://abc123.ngrok.io/save-level"
    payload = {"user_id": user_id, "level": level}
    
    try:
        response = requests.post(api_url, json=payload)
        if response.status_code == 200:
            print("等级已成功保存到本地文件!")
        else:
            print(f"保存失败,状态码:{response.status_code}")
    except requests.exceptions.RequestException as e:
        print(f"请求出错:{e}")

⚠️ 注意:ngrok免费版每次重启都会改变URL,如果你想长期用,要么升级ngrok付费版,要么自己配置端口转发+固定公网IP。而且这种方式只适合个人测试用,生产环境还是推荐用数据库。

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

火山引擎 最新活动