You need to enable JavaScript to run this app. 如何在普通同步函数中调用await异步函数 实现Tweepy推文转发到Discord
优惠活动
大模型
产品
解决方案
定价
更多

如何在普通同步函数中调用await异步函数 实现Tweepy推文转发到Discord

问题核心

discord.py 是异步框架,发消息等接口必须在异步上下文内通过 await 调用,而 Tweepy Stream 的 on_status 是同步回调,且你通过 threaded=True 开启了独立线程运行流服务,两套逻辑运行在不同的线程和执行上下文里,无法直接在同步方法中调用异步函数。

解决思路
  • 提前获取 Discord 客户端运行绑定的异步事件循环引用,传入 TweepyStream 实例
  • 在同步的 on_status 回调中,通过线程安全的方法将发消息的异步任务提交到 Discord 对应的事件循环中执行
  • 提前存储目标 Discord 频道 ID,客户端就绪后预获取频道实例,避免每次发消息重复查询
修改后的可运行代码
import discord
import tweepy
import asyncio

# 替换为你自己的配置项
TARGET_DISCORD_CHANNEL_ID = 1234567890 # 目标Discord频道的数字ID
TWITTER_API_KEYS = {
    "consumer_key": "你的Twitter Consumer Key",
    "consumer_secret": "你的Twitter Consumer Secret",
    "access_token": "你的Twitter Access Token",
    "access_token_secret": "你的Twitter Access Token Secret"
}
DISCORD_BOT_TOKEN = "你的Discord机器人Token"

class Client(discord.Client):
    async def on_ready(self):
        print('Discord客户端已就绪')
        # 初始化Tweepy流,传入Discord客户端和对应事件循环
        self.tweepy_stream = TweepyStream(
            **TWITTER_API_KEYS,
            discord_client=self,
            loop=self.loop
        )
        # 独立线程运行流,不会阻塞Discord事件循环
        self.tweepy_stream.filter(follow = [], threaded=True)

class TweepyStream(tweepy.Stream):
    def __init__(self, *args, discord_client=None, loop=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.discord_client = discord_client
        self.loop = loop
        self.target_channel = None

    def on_connect(self):
        print('已连接到Twitter流')
        # 预获取目标频道实例
        self.target_channel = self.discord_client.get_channel(TARGET_DISCORD_CHANNEL_ID)

    def on_status(self, status):
        print(status.text)
        if not self.loop or not self.target_channel:
            return
        # 构造发消息的异步协程
        async def send_to_discord():
            await self.target_channel.send(f"收到新推文:\n{status.text}")
        # 线程安全地将协程提交到Discord的事件循环执行
        asyncio.run_coroutine_threadsafe(send_to_discord(), self.loop)

# 启动Discord客户端,v2.0及以上版本必须显式声明Intents
client = Client(intents=discord.Intents.default())
client.run(DISCORD_BOT_TOKEN)
注意事项
  • 确保你的 Discord 机器人已经被邀请到目标服务器,且拥有对应频道的发消息权限
  • 如果需要推送的推文包含图片、链接等附加内容,可以自行扩展 send_to_discord 协程的逻辑,拼接 embed 消息格式
  • 不要将 Tweepy 流的启动代码放在 client.run() 之后,client.run() 是阻塞方法,后续代码不会被执行,放在 on_ready 回调中可以保证 Discord 客户端初始化完成后再启动流服务

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 21:36:05