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

Discord机器人无法保留字符串值,Heroku部署后次日重置问题咨询

问题根源:Heroku Dyno 重启导致内存数据丢失

这绝对不是你的代码逻辑问题,问题出在Heroku Dyno的运行机制上。

为什么swingsMessage会被重置?

你现在把swingsMessage存在机器人进程的内存里,但Heroku的免费Dyno有几个特性会导致进程重启:

  • 免费Dyno每天会自动休眠6小时,唤醒时会完全重启你的机器人进程
  • Heroku会定期对所有Dyno进行系统维护或重启(不管免费还是付费版)
  • 当你的应用超过30分钟没有收到请求时,免费Dyno也会进入休眠,再次被触发时重启进程

每次重启都会重新执行你的代码,内存里的swingsMessage自然会被重置为初始值"Update me"。

解决办法:用持久化存储保存数据

要搞定这个问题,你得把swingsMessage的内容存到持久化介质里,而不是依赖进程内存。这里给你两个适合Heroku环境的简单方案:

方案1:用Heroku Redis(轻量键值存储)

Heroku提供免费的Redis插件,非常适合存储这种简单的键值对数据。步骤如下:

  1. 先在Heroku控制台给你的应用添加Redis插件
  2. 安装redis依赖:pip install redis
  3. 修改代码如下:
import discord
from discord.ext import commands
import redis
import os

# 从Heroku环境变量获取Redis连接地址
r = redis.from_url(os.environ.get("REDIS_URL"))

# 初始化默认值(如果Redis里还没有这个键)
if not r.exists("swings_message"):
    r.set("swings_message", "Update me")

client = commands.Bot(command_prefix = "!")

@client.command()
async def swings(ctx):
    # 从Redis读取数据,注意转成字符串
    swingsMessage = r.get("swings_message").decode('utf-8')
    await ctx.send(swingsMessage)

@client.command()
async def update(ctx,*,message):
    if str(ctx.message.author) == "buysellshort#9420":
        r.set("swings_message", message)
        await ctx.send("内容已成功更新!")

# 记得从环境变量读取Discord Token,不要硬编码
client.run(os.environ.get("DISCORD_TOKEN"))

方案2:用Heroku PostgreSQL(更适合扩展)

如果你的机器人以后要加更多功能,PostgreSQL会是更稳定的选择。步骤如下:

  1. 在Heroku控制台给应用添加PostgreSQL插件
  2. 安装psycopg2-binary依赖:pip install psycopg2-binary
  3. 修改代码如下:
import discord
from discord.ext import commands
import psycopg2
import os

# 从Heroku环境变量获取数据库连接地址
DATABASE_URL = os.environ.get("DATABASE_URL")
conn = psycopg2.connect(DATABASE_URL)
c = conn.cursor()

# 创建存储表(第一次运行时自动创建)
c.execute('''CREATE TABLE IF NOT EXISTS swings_message
             (id SERIAL PRIMARY KEY, content TEXT NOT NULL)''')
# 插入初始默认值(如果表为空)
c.execute('SELECT content FROM swings_message')
result = c.fetchone()
if not result:
    c.execute('INSERT INTO swings_message (content) VALUES (%s)', ("Update me",))
    conn.commit()

client = commands.Bot(command_prefix = "!")

@client.command()
async def swings(ctx):
    c.execute('SELECT content FROM swings_message LIMIT 1')
    swingsMessage = c.fetchone()[0]
    await ctx.send(swingsMessage)

@client.command()
async def update(ctx,*,message):
    if str(ctx.message.author) == "buysellshort#9420":
        c.execute('UPDATE swings_message SET content = %s WHERE id = 1', (message,))
        conn.commit()
        await ctx.send("内容已更新!")

client.run(os.environ.get("DISCORD_TOKEN"))
额外提醒
  • 不要在Heroku上用SQLite!Heroku的文件系统是临时的,每次重启都会重置到部署时的状态,SQLite文件里的数据会丢失。
  • 记得把Discord Token和数据库连接信息放到Heroku的环境变量里,不要硬编码到代码里,避免泄露敏感信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 12:57:54