如何在discord.py的独立文件someFunc.py中向指定频道发消息?
解决定时任务发送Discord消息的方案
核心问题说明
你遇到的是循环导入(bot.py导入someFunc.py,反向导入会触发循环依赖错误)加上异步API与同步定时任务的适配问题,下面是两种可行的解决思路:
方案1:给定时任务传递频道对象
Discord客户端必须完成初始化(on_ready事件触发后)才能正确获取频道,所以要把定时任务的添加逻辑放到客户端就绪后执行:
修改someFunc.py
让func接受频道对象作为参数,同时适配异步消息发送:
import asyncio async def func(channel): # 发送目标消息 await channel.send("定时推送的消息内容")
修改bot.py
在on_ready事件中获取频道并传递给定时任务,用asyncio.run桥接同步调度器和异步Discord API:
import os import someFunc import discord from discord.ext import commands from dotenv import load_dotenv from apscheduler.schedulers.background import BackgroundScheduler import asyncio load_dotenv() TOKEN = os.getenv('TOKEN') # 开启必要的Intents,否则无法发送消息或获取频道 intents = discord.Intents.default() intents.message_content = True client = commands.Bot(command_prefix='!', intents=intents) scheduler = BackgroundScheduler(timezone="Asia/Seoul") @client.event async def on_ready(): print(f'已登录为 {client.user}') # 替换为你的目标频道ID(纯数字) target_channel_id = 123456789012345678 target_channel = client.get_channel(target_channel_id) if target_channel: # 添加定时任务,用lambda包装传递频道参数 scheduler.add_job( lambda: asyncio.run(someFunc.func(target_channel)), 'cron', hour='19', minute='47,48' ) scheduler.start() print("定时任务已启动") else: print("无法找到目标频道,请检查频道ID是否正确") try: client.run(TOKEN) except (KeyboardInterrupt, SystemExit): scheduler.shutdown() print("定时任务已关闭")
方案2:通过全局回调函数解耦
在someFunc中定义一个全局变量存储发送消息的方法,由bot.py在初始化后赋值,避免直接传递对象:
修改someFunc.py
import asyncio # 全局变量:存储发送消息的异步方法 send_message_callback = None def func(): if send_message_callback: # 调用预设的发送方法 asyncio.run(send_message_callback("定时推送的消息内容"))
修改bot.py
在on_ready事件中把发送消息的逻辑赋值给someFunc的全局变量:
import os import someFunc import discord from discord.ext import commands from dotenv import load_dotenv from apscheduler.schedulers.background import BackgroundScheduler import asyncio load_dotenv() TOKEN = os.getenv('TOKEN') intents = discord.Intents.default() intents.message_content = True client = commands.Bot(command_prefix='!', intents=intents) scheduler = BackgroundScheduler(timezone="Asia/Seoul") async def send_to_target_channel(content): # 替换为你的目标频道ID target_channel_id = 123456789012345678 target_channel = client.get_channel(target_channel_id) if target_channel: await target_channel.send(content) @client.event async def on_ready(): print(f'已登录为 {client.user}') # 给someFunc设置发送消息的回调 someFunc.send_message_callback = send_to_target_channel # 添加定时任务 scheduler.add_job(someFunc.func, 'cron', hour='19', minute='47,48') scheduler.start() print("定时任务已启动") try: client.run(TOKEN) except (KeyboardInterrupt, SystemExit): scheduler.shutdown() print("定时任务已关闭")
注意事项
- 必须在Discord开发者面板开启对应机器人的Message Content Intent,否则无法发送消息。
- 频道ID需要是纯数字,你可以在Discord开启开发者模式后右键频道复制ID。
- BackgroundScheduler是同步线程,调用异步的Discord API必须用
asyncio.run包裹,否则会报错。
内容的提问来源于stack exchange,提问作者dohyunii
相关产品推荐
相关产品推荐

