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

使用Telethon+Telebot+asyncio时,get_entity()调用致程序冻结

解决Telethon与Telebot异步混用中get_entity(url)冻结的问题

问题现象

  • 同时用Telethon解析频道订阅者列表、Telebot搭建机器人,依赖asyncio实现异步逻辑
  • 异步函数执行到channel = await client.get_entity(url)时,程序直接冻结,无任何异常或警告输出
  • 替换代码为channel = await client.get_input_entity(InputPeerChannelFromMessage('Channel', message.id, message.chat.id))后,程序恢复正常运行
  • 单独使用Telethon时,get_entity("t.me/channellink")可以正常工作

问题根源

Telebot(python-telegram-bot)的异步事件循环与Telethon的网络请求调度逻辑存在兼容性冲突。get_entity(url)需要发起网络请求解析频道实体,但在Telebot的循环上下文里,这个IO操作被阻塞,无法正常完成调度。

可行解决方案

1. 利用消息上下文调用get_input_entity

既然已经验证InputPeerChannelFromMessage可以正常获取实体,直接沿用这种方式:

from telethon.tl.types import InputPeerChannelFromMessage

# 在Telebot的消息处理异步函数内
channel = await client.get_input_entity(InputPeerChannelFromMessage('Channel', message.id, message.chat.id))

这种方式直接基于当前消息的上下文获取频道实体,跳过了get_entity(url)需要的额外网络解析步骤,规避了两个库的循环冲突。

2. 给Telethon单独分配事件循环线程

让Telethon和Telebot各自运行在独立的事件循环中,从根源上解决循环干扰问题:

import asyncio
from threading import Thread

def run_telethon_loop(client):
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_until_complete(client.start())
    loop.run_forever()

# 启动Telethon的独立线程
telethon_thread = Thread(target=run_telethon_loop, args=(client,), daemon=True)
telethon_thread.start()

# 在Telebot的处理函数中,跨线程调用Telethon方法
async def handle_bot_message(message):
    url = "t.me/channellink"
    coro = client.get_entity(url)
    # 将协程提交到Telethon的事件循环执行
    future = asyncio.run_coroutine_threadsafe(coro, asyncio.get_event_loop())
    channel = future.result()
    # 后续处理订阅者列表的逻辑

3. 改用Bot API直接获取频道信息(需求允许时)

如果仅需要频道的基础信息,可直接通过Telebot调用官方Bot API的getChat方法,完全避开Telethon的实体解析逻辑:

# 在Telebot的消息处理函数内
chat = await bot.get_chat("@channelusername")
# chat对象包含频道ID、标题等核心信息,可用于后续逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 21:52:38