运行Discord机器人触发RuntimeError: no running event loop问题求助
解决Discord机器人RuntimeError: no running event loop错误
在树莓派3上运行一款监控Fortnite版本及服务器状态的Discord机器人时,触发RuntimeError: no running event loop错误,尝试多个方案未解决,以下是问题详情及代码:
错误回溯
Traceback (most recent call last): File "/home/monksbot/testfordiscordbot.py", line 41, in <module> version_update_background_task.start() File "/home/monksbot/.local/lib/python3.9/site-packages/discord/ext/tasks/__init__.py", line 398, in start self._task = asyncio.create_task(self._loop(*args, **kwargs)) File "/usr/lib/python3.9/asyncio/tasks.py", line 360, in create_task loop = events.get_running_loop() RuntimeError: no running event loop
原代码
from discord.ext import tasks import discord import requests client = discord.Client(intents=discord.Intents.all()) slash = SlashCommand(client, sync_commands=True) guild_ids = [1018805336003584070] @client.event async def on_ready(): activity = discord.Activity(type=discord.ActivityType.watching, name="Fortnite APIs") await client.change_presence(status=discord.Status.online, activity=activity) @tasks.loop(seconds=10) async def version_update_background_task(): aes = requests.get("https://fortnitecentral.gmatrixgames.ga/api/v1/aes") version = aes.json()["version"] mainaes = aes.json()["mainKey"] channel = client.get_channel(1018805336917950487) if version != "21.51": await channel.send(f"@here NEW VERSION DETECTED: Fortnite v{version} is now avaliable for download!\n\n> Main Key: {mainaes}") url = 'https://fortnite-api.com/images/map.png' req = requests.get(url) with open('images/Map.png', 'wb') as f: f.write(req.content) await channel.send("New Fortnite Map Detected!", file=discord.File('images/Map.png')) version_update_background_task.end() @tasks.loop(seconds=10) async def lightswitch_task(): lightswitch = requests.get("https://fn-api.com/api/status") onoff = lightswitch.json()["data"]["status"] message = lightswitch.json()["data"]["message"] channel = client.get_channel(1018805336917950487) if onoff != "UP": await channel.send(f"@here {message}\n\n> Fortnite servers are now {onoff} for maintenance!", file=discord.File('images/BEGUN.png')) lightswitch_task.end() @lightswitch_task.before_loop async def lightswitch_task_before_loop(): await client.wait_until_ready() @version_update_background_task.before_loop async def version_update_background_task_before_loop(): await client.wait_until_ready() version_update_background_task.start() lightswitch_task.start() client.run("no")
问题原因及解决方案
核心问题
你在全局作用域直接调用version_update_background_task.start()和lightswitch_task.start(),此时Discord客户端的事件循环还未启动(client.run()才会启动事件循环),而tasks.loop的start()方法需要依赖已运行的事件循环,因此触发错误。
修复步骤
- 将任务启动逻辑移至
on_ready事件中:当客户端成功连接Discord并准备就绪后,再启动后台任务,此时事件循环已正常运行。 - 修正
on_ready函数的缩进错误:原代码中await client.change_presence未缩进,属于语法错误,会导致函数逻辑异常。 - 补充缺失的导入:原代码使用了
SlashCommand但未导入,需添加from discord_slash import SlashCommand。 - (可选但推荐)替换同步请求为异步请求:
requests.get是同步阻塞调用,会卡住Discord机器人的事件循环,建议改用aiohttp实现异步HTTP请求,避免机器人响应延迟。
修改后的完整代码
from discord.ext import tasks import discord import requests from discord_slash import SlashCommand # 补充缺失的导入 import os # 自动创建images目录,避免写入文件报错 os.makedirs('images', exist_ok=True) client = discord.Client(intents=discord.Intents.all()) slash = SlashCommand(client, sync_commands=True) guild_ids = [1018805336003584070] @client.event async def on_ready(): activity = discord.Activity(type=discord.ActivityType.watching, name="Fortnite APIs") await client.change_presence(status=discord.Status.online, activity=activity) # 修正缩进 # 在客户端就绪后启动任务 version_update_background_task.start() lightswitch_task.start() print("机器人已就绪,任务启动完成") @tasks.loop(seconds=10) async def version_update_background_task(): aes = requests.get("https://fortnitecentral.gmatrixgames.ga/api/v1/aes") version = aes.json()["version"] mainaes = aes.json()["mainKey"] channel = client.get_channel(1018805336917950487) if version != "21.51": await channel.send(f"@here NEW VERSION DETECTED: Fortnite v{version} is now available for download!\n\n> Main Key: {mainaes}") url = 'https://fortnite-api.com/images/map.png' req = requests.get(url) with open('images/Map.png', 'wb') as f: f.write(req.content) await channel.send("New Fortnite Map Detected!", file=discord.File('images/Map.png')) version_update_background_task.end() @tasks.loop(seconds=10) async def lightswitch_task(): lightswitch = requests.get("https://fn-api.com/api/status") onoff = lightswitch.json()["data"]["status"] message = lightswitch.json()["data"]["message"] channel = client.get_channel(1018805336917950487) if onoff != "UP": await channel.send(f"@here {message}\n\n> Fortnite servers are now {onoff} for maintenance!", file=discord.File('images/BEGUN.png')) lightswitch_task.end() @lightswitch_task.before_loop async def lightswitch_task_before_loop(): await client.wait_until_ready() @version_update_background_task.before_loop async def version_update_background_task_before_loop(): await client.wait_until_ready() # 移除全局的任务启动调用,移至on_ready中 client.run("你的机器人Token")
额外提示
- 替换
"你的机器人Token"为实际的Discord机器人令牌,不要泄露令牌。 - 确保树莓派上已安装所有依赖包:
pip install discord.py discord-py-slash-command requests
内容的提问来源于stack exchange,提问作者Monks
相关产品推荐
相关产品推荐

