Discord股票机器人called_once_a_day报错:RuntimeError: no running event loop
问题分析与解决方案
核心问题
报错RuntimeError: no running event loop是因为在asyncio事件循环未启动时调用了定时任务的start()方法,同时脚本顶层直接执行called_once_a_day.start(),此时Discord bot的事件循环还未初始化,导致无法创建异步任务。另外代码中还存在同步阻塞调用的隐患。
修复步骤
1. 调整定时任务启动时机
将called_once_a_day.start()移至bot的on_ready事件回调中,确保在bot登录完成、事件循环已启动后再启动定时任务:
@bot.event async def on_ready(): print(f"已登录为 {bot.user}") # 避免重复启动任务 if not called_once_a_day.is_running(): called_once_a_day.start()
2. 替换同步HTTP请求为异步调用
原代码中requests.get()是同步阻塞方法,会卡住整个bot的事件循环,改用异步HTTP库aiohttp替代:
先安装依赖:
pip install aiohttp
修改定时任务函数:
import aiohttp from bs4 import BeautifulSoup from discord.ext import tasks, commands @tasks.loop(hours=24) async def called_once_a_day(): URL = "https://finance.yahoo.com/quote/^QMI" # 异步请求页面 async with aiohttp.ClientSession() as session: async with session.get(URL) as response: page_text = await response.text() soup = BeautifulSoup(page_text, "html.parser") premarket = "" try: price_container = soup.find("div", {"class":"My(6px) Pos(r) smartphone_Mt(6px)"}) if price_container: spans = price_container.find_all("span") if len(spans) >= 2: current_price = spans[0] change = spans[1] premarket = f"NASDAQ 100 Pre Market\t{current_price.text}\t{change.text}" else: premarket = "数据不足" else: premarket = "未找到数据容器" except Exception as e: premarket = f"获取数据失败: {str(e)}" # 遍历频道发送消息 for guild in bot.guilds: for channel in guild.channels: try: embed = get_news() # 若get_news是同步函数,建议也改为异步避免阻塞 await channel.send(embed=embed) await channel.send(premarket) except Exception as e: print(f"发送到频道 {channel.name} 失败: {str(e)}") continue
3. 优化异常处理与元素查找
- 移除宽泛的
except:,改为捕获具体异常并打印错误信息,便于调试 - 增加元素存在性判断,避免索引越界报错
内容的提问来源于stack exchange,提问作者Kartikay Mehta
相关产品推荐
相关产品推荐

