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

Telethon事件处理器与asyncio任务并行时无法触发问题排查

解决Telethon客户端与Socket监听并发运行的问题

你的问题核心在于同步Socket操作阻塞了asyncio事件循环,导致Telethon的消息事件无法被处理。asyncio是单线程事件驱动模型,任何同步阻塞调用(比如server_socket.accept())都会占用整个事件循环,让其他异步任务(比如Telethon的事件监听)得不到执行机会。另外,你的main()函数里没有await asyncio.gather(),这会导致协程调度出现问题。

解决方案1:使用asyncio异步Socket API(推荐)

直接用asyncio提供的start_server实现异步Socket监听,全程使用异步操作,避免阻塞事件循环:

import asyncio
from telethon import TelegramClient, events

api_id = 你的API_ID
api_hash = '你的API_HASH'
client = TelegramClient('anon', api_id, api_hash)

@client.on(events.NewMessage)
async def onMessage(event):
    print("收到Telegram消息:", event.raw_text)

async def run_client():
    await client.start()
    await client.run_until_disconnected()

async def handle_socket_client(reader, writer):
    client_address = writer.get_extra_info('peername')
    print("Client connected:", client_address)
    # 可添加Socket消息处理逻辑,示例读取数据
    data = await reader.read(100)
    message = data.decode()
    print(f"收到来自{client_address}的消息: {message}")
    
    writer.close()
    await writer.wait_closed()

async def socket_listener():
    server = await asyncio.start_server(handle_socket_client, '127.0.0.1', 8888)
    async with server:
        await server.serve_forever()

async def main():
    await asyncio.gather(run_client(), socket_listener())

if __name__ == "__main__":
    asyncio.run(main())

解决方案2:用线程池包装同步Socket操作

如果必须保留同步Socket代码,可把阻塞的accept()操作放到线程池中执行,避免阻塞事件循环:

import asyncio
from telethon import TelegramClient, events
import socket

api_id = 你的API_ID
api_hash = '你的API_HASH'
client = TelegramClient('anon', api_id, api_hash)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('127.0.0.1', 8888))
server_socket.listen(5)

@client.on(events.NewMessage)
async def onMessage(event):
    print("收到Telegram消息:", event.raw_text)

async def run_client():
    await client.start()
    await client.run_until_disconnected()

async def socket_listener():
    loop = asyncio.get_running_loop()
    while True:
        # 把同步accept放到线程池执行,不阻塞事件循环
        client_socket, client_address = await loop.run_in_executor(None, server_socket.accept)
        print("Client connected:", client_address)
        # 实际Socket处理逻辑也需避免同步阻塞,建议异步化

async def main():
    await asyncio.gather(run_client(), socket_listener())

if __name__ == "__main__":
    try:
        asyncio.run(main())
    finally:
        server_socket.close()

关键说明

  1. 避免同步阻塞:asyncio事件循环不能被同步操作卡住,所有长时间运行的操作需异步化或放到线程/进程池。
  2. await asyncio.gather():asyncio.gather()返回协程对象,必须用await才能调度任务执行,否则main()协程会直接结束,任务无法正常运行。
  3. Telethon的run_until_disconnected()本身是持续运行的异步函数,只要事件循环不被阻塞,就能正常监听并处理Telegram事件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 11:22:01