You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Telethon脚本整合到异步事件循环中?

问题:整合pydle IRC机器人与Telethon Telegram机器人时的事件循环阻塞问题

我有两个机器人:

  • 基于pydle实现的IRC机器人,代码如下:
async def start_ircbot ():
    try:
        client = MyOwnBot(NICK, 
                       realname=REALNAME,
                       sasl_username=SASL_USERNAME,
                       sasl_password=SASL_PASSWORD,
                       sasl_identity=SASL_IDENTITY,)

        loop = asyncio.get_event_loop()
        asyncio.ensure_future(client.connect(HOST, PORT, tls=True, tls_verify=False), loop=loop)
        loop.run_forever()
        loop.close()
    except Exception as e:
        print (e)
  • 基于Telethon实现的Telegram机器人,代码如下:
@client.on(events.NewMessage)
async def my_event_handler(event):
    ...

async def start_client ():
    print ("Telegram monitor started...")
    await client.start()
    await client.run_until_disconnected()

两者单独运行均正常,但整合时遇到以下问题:

  1. 按以下顺序启动,Telegram的my_event_handler无法接收新消息:
import Notifier

...

async def main():
    await asyncio.gather (Notifier.start_client (), start_ircbot ())

asyncio.run(main())
  1. 调换启动顺序后,脚本直接卡在启动阶段:
await asyncio.gather (start_ircbot (), Notifier.start_client ())

怀疑是事件循环相关问题,求解决方法。


问题原因与解决方法

核心问题

start_ircbot函数中的loop.run_forever()是阻塞式调用——它会独占当前事件循环,导致后续异步任务(如Telegram机器人启动)无法执行;若先执行start_ircbot,该调用会直接卡住整个程序,让start_client永远得不到运行机会。此外,手动获取事件循环并调用ensure_future的方式,和asyncio.run的循环管理逻辑冲突。

修改方案

重构start_ircbot函数,移除手动循环控制逻辑,让pydle客户端融入asyncio.run管理的全局事件循环:

async def start_ircbot():
    try:
        client = MyOwnBot(
            NICK, 
            realname=REALNAME,
            sasl_username=SASL_USERNAME,
            sasl_password=SASL_PASSWORD,
            sasl_identity=SASL_IDENTITY,
        )
        # 直接await连接任务,无需手动创建future或调用run_forever
        await client.connect(HOST, PORT, tls=True, tls_verify=False)
        # 等待IRC客户端断开连接,保持协程持续运行
        await client.wait_for_disconnect()
    except Exception as e:
        print(e)

整合后的main函数

修改后,直接用asyncio.gather同时启动两个任务即可,顺序不再影响:

import Notifier
import asyncio

async def main():
    await asyncio.gather(Notifier.start_client(), start_ircbot())

asyncio.run(main())

原理说明

  • pydle的connect本身是异步函数,await client.connect(...)会让客户端在当前事件循环中初始化连接并运行,无需手动启动独立循环。
  • client.wait_for_disconnect()会阻塞当前协程直到IRC客户端断开,确保两个机器人的协程在同一事件循环中并发执行,不会互相阻塞。
  • asyncio.gather会同时调度两个异步任务,完美适配asyncio.run的循环管理逻辑,解决了之前的阻塞问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 21:05:22