You need to enable JavaScript to run this app. Discord.py如何创建无需事件/循环触发、可主动调用的notify函数
优惠活动
大模型
产品
解决方案
定价
更多

Discord.py如何创建无需事件/循环触发、可主动调用的notify函数

原有代码的错误原因
  • 第一份代码的核心问题:client.run()是阻塞运行的方法,调用后会持续运行事件循环直到客户端断开,它后面的create_task代码永远不会执行。
  • 第二份代码的核心问题:Discord.py 的 Client 类没有公开的log()方法,也不能将connect()和run()混用,手动拆分启动流程会导致事件循环、登录认证初始化错误,进而触发各类HTTP请求报错。
正确实现思路

客户端需要持续运行维持和Discord网关的连接,所有主动调用的通知逻辑不需要依赖事件触发或循环,只要能将异步的notify协程提交到客户端的事件循环中执行即可。

完整可运行代码示例
import os
import asyncio
import discord
from dotenv import load_dotenv

# 加载环境变量中的TOKEN、频道ID
load_dotenv()
intents = discord.Intents.default()
# 初始化全局客户端实例
client = discord.Client(intents=intents)

async def notify(message: str):
    """主动发送通知到指定频道的方法"""
    # 兜底等待客户端初始化完成,只需执行一次
    await client.wait_until_ready()
    channel_id = int(os.getenv('CHANNEL_ID'))
    channel = client.get_channel(channel_id)
    if not channel:
        print(f"未找到ID为{channel_id}的频道")
        return
    await channel.send(message)

# 客户端启动完成回调(仅用于初始化,通知逻辑不依赖此事件)
@client.event
async def on_ready():
    print(f"客户端已登录,用户ID:{client.user.id}")
    # 可选:启动后自动发一次测试通知
    await notify("客户端已就绪")

# --- 业务逻辑调用示例 ---
# 以下为同步业务代码,不需要放在Discord事件中,触发时直接调用即可
def sync_business_task():
    # 这里可以替换为你的任意业务逻辑:比如文件处理、第三方接口回调、脚本执行完成等
    print("同步业务逻辑执行完成")
    # 将异步notify协程提交到Discord事件循环中执行,无需等待返回
    asyncio.run_coroutine_threadsafe(notify("业务执行完成"), client.loop)

if __name__ == "__main__":
    # 启动客户端,阻塞运行直到手动停止
    client.run(os.getenv('CLIENT_TOKEN'))
常见注意事项
  • 频道ID需要传入整数,从环境变量读取后必须转成int类型,否则get_channel会返回None。
  • 如果你的业务逻辑本身就是异步的,可以直接在任意异步任务中await notify("xxx"),不需要额外用run_coroutine_threadsafe。
  • wait_until_ready()只会在客户端首次初始化时阻塞,后续调用会直接返回,不存在重复等待的性能问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.25 20:36:02