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

Python用Telethon多线程创建Telegram频道遇Asyncio卡顿求助

解决思路

1. 禁止跨线程复用同一个Telethon Client实例

Telethon的Client对象不是线程安全的,它内部的连接状态、事件循环绑定都是线程专属的。跨线程复用同一个client会导致连接阻塞、事件循环冲突,这是代码卡住的核心原因。

每个线程必须创建独立的Client实例,示例:

def thread_func(username, desc):
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    # 每个线程单独初始化Client,会话文件用线程ID区分避免冲突
    client = TelegramClient(f'session_{threading.get_ident()}', API_ID, API_HASH, loop=loop)
    try:
        loop.run_until_complete(client.start())
        result = loop.run_until_complete(createChannel(client, username, desc))
    finally:
        loop.run_until_complete(client.disconnect())
        loop.close()
    return result

同时修改createChannel函数,把client作为参数传入,避免全局复用:

async def createChannel(client, username, desc):
    # 先确保连接正常
    if not client.is_connected():
        await client.connect()
    
    chn = await client(CreateChannelRequest(username, desc, megagroup=False))
    new_channel = chn.chats[0]
    update_response = await client(UpdateUsernameRequest(
        InputPeerChannel(channel_id=new_channel.id, access_hash=new_channel.access_hash),
        username
    ))
    return update_response

2. 修复错误处理逻辑

原函数的裸except会捕获所有异常(包括异步任务内部错误),且重复代码冗余。改成先检查连接状态,只捕获特定异常(比如连接类错误):

async def createChannel(client, username, desc):
    try:
        if not client.is_connected():
            await client.connect()
        
        chn = await client(CreateChannelRequest(username, desc, megagroup=False))
        new_channel = chn.chats[0]
        return await client(UpdateUsernameRequest(
            InputPeerChannel(channel_id=new_channel.id, access_hash=new_channel.access_hash),
            username
        ))
    except ConnectionError as e:
        # 仅处理连接类错误,重新尝试连接
        await client.disconnect()
        await client.connect()
        chn = await client(CreateChannelRequest(username, desc, megagroup=False))
        new_channel = chn.chats[0]
        return await client(UpdateUsernameRequest(
            InputPeerChannel(channel_id=new_channel.id, access_hash=new_channel.access_hash),
            username
        ))

3. 优先使用异步并发替代多线程

Telethon本身是异步库,用asyncio.gather实现并发比多线程更高效,也不会有事件循环冲突问题:

async def main():
    client = TelegramClient('session_main', API_ID, API_HASH)
    await client.start()
    
    # 批量创建频道,并发执行
    tasks = [
        createChannel(client, "user_chn1", "测试频道1"),
        createChannel(client, "user_chn2", "测试频道2"),
        createChannel(client, "user_chn3", "测试频道3")
    ]
    results = await asyncio.gather(*tasks)
    await client.disconnect()

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

4. 子线程中正确运行异步任务

如果必须用多线程,要确保子线程的事件循环完整驱动异步任务,不能仅设置循环就直接调用await。正确写法是用loop.run_until_complete包裹异步任务:

import threading
import asyncio
from telethon import TelegramClient, functions

def run_create_channel(username, desc):
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    
    client = TelegramClient(f'session_{threading.get_ident()}', API_ID, API_HASH, loop=loop)
    try:
        loop.run_until_complete(client.start())
        result = loop.run_until_complete(createChannel(client, username, desc))
        print(f"创建结果:{result}")
    finally:
        loop.run_until_complete(client.disconnect())
        loop.close()

# 启动多线程
thread1 = threading.Thread(target=run_create_channel, args=("test_chn1", "测试描述1"))
thread2 = threading.Thread(target=run_create_channel, args=("test_chn2", "测试描述2"))
thread1.start()
thread2.start()
thread1.join()
thread2.join()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 09:20:39