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

Telethon报错ValueError: readexactly size不能小于零如何解决?

解决Telethon中ValueError: readexactly size can not be less than zero异常

问题描述

我遇到了如下报错,推测可能和频繁请求有关,但加了异常捕获代码还是没用。试过在代码不同位置用多种方式捕获异常,都没效果,查了论坛和库文档也没找到解决方案。

报错信息

Unexpected exception in the receive loop
Traceback (most recent call last):
  File "C:\Users\fazuq\AppData\Local\Programs\Python\Python39\lib\site-packages\telethon\network\connection\connection.py", line 324, in _recv_loop
    data = await self._recv()
  File "C:\Users\fazuq\AppData\Local\Programs\Python\Python39\lib\site-packages\telethon\network\connection\connection.py", line 367, in _recv
    return await self._codec.read_packet(self._reader)
  File "C:\Users\fazuq\AppData\Local\Programs\Python\Python39\lib\site-packages\telethon\network\connection\tcpfull.py", line 27, in read_packet
    body = await reader.readexactly(packet_len - 8)
  File "C:\Users\fazuq\AppData\Local\Programs\Python\Python39\lib\asyncio\streams.py", line 709, in readexactly
    raise ValueError('readexactly size can not be less than zero')
ValueError: readexactly size can not be less than zero

我的代码

async def get_voice_messages(client: TelegramClient, dialog_id: int):
    try:
        messages: list = await client.get_messages(dialog_id, None, filter = InputMessagesFilterVoice)
    except ValueError:
        print('я тута')
        return
    except:
        print('или тута')
        return
    print('See dialog: {}'.format(dialog_id))
    for message in messages:
        try:
            if message.out:
                # await client.delete_messages(message.peer_id.user_id, message_ids=[message.id])
                print('Success delete message: {} from peer: {}'.format(message.id, message.peer_id.user_id))
        except:
            print('No have voice messages!')


async def get_dialog_list() -> None:
    loop = asyncio.get_event_loop()
    async with TelegramClient(config['session_name'], config['api_id'], config['api_hash'], loop = loop) as client:
        try:
            dialogs: list = await client.get_dialogs(ignore_migrated = True)
        except ValueError:
            return

        tasks: list = []
        for dialog in dialogs:
            try:
                if not dialog.is_channel and not dialog.is_group and not dialog.entity.bot:
                    tasks.append(asyncio.create_task(get_voice_messages(client, dialog.id)))
            except ValueError:
                continue
        start_tasks: tuple = await asyncio.gather(*tasks)
        print('Success delete all messages!')

def start_thread() -> None:
    asyncio.run(get_dialog_list())

解决方法

  • 限制并发请求数量:当前代码一次性创建所有对话的请求任务,并发过高容易触发Telegram限制或连接异常。用asyncio.Semaphore控制并发数,比如设为5:
    # 修改get_dialog_list函数
    async def get_dialog_list() -> None:
        loop = asyncio.get_event_loop()
        semaphore = asyncio.Semaphore(5)  # 限制同时5个请求
        async with TelegramClient(config['session_name'], config['api_id'], config['api_hash'], loop = loop) as client:
            try:
                dialogs: list = await client.get_dialogs(ignore_migrated = True)
            except ValueError:
                return
    
            tasks: list = []
            for dialog in dialogs:
                try:
                    if not dialog.is_channel and not dialog.is_group and not dialog.entity.bot:
                        tasks.append(asyncio.create_task(get_voice_messages(client, dialog.id, semaphore)))
                except ValueError:
                    continue
            start_tasks: tuple = await asyncio.gather(*tasks)
            print('Success delete all messages!')
    
    # 修改get_voice_messages函数
    async def get_voice_messages(client: TelegramClient, dialog_id: int, semaphore):
        async with semaphore:
            try:
                messages: list = await client.get_messages(dialog_id, None, filter = InputMessagesFilterVoice)
            except ValueError:
                print('я тута')
                return
            except:
                print('или тута')
                return
            print('See dialog: {}'.format(dialog_id))
            for message in messages:
                try:
                    if message.out:
                        # await client.delete_messages(message.peer_id.user_id, message_ids=[message.id])
                        print('Success delete message: {} from peer: {}'.format(message.id, message.peer_id.user_id))
                except:
                    print('No have voice messages!')
    
  • 更换连接类型:报错来自TCPFull连接的数据包解析,换成TCPAbridged连接可降低这类问题:
    from telethon.network.connection.tcpabridged import TCPAbridged
    
    # 创建客户端时指定连接
    async with TelegramClient(config['session_name'], config['api_id'], config['api_hash'], loop=loop, connection=TCPAbridged) as client:
        # 原有逻辑
    
  • 升级Telethon版本:该错误可能是旧版本的bug,执行命令升级:
    pip install --upgrade telethon
    
  • 添加请求间隔:遍历对话时加短暂延迟,避免请求过于密集:
    for dialog in dialogs:
        try:
            if not dialog.is_channel and not dialog.is_group and not dialog.entity.bot:
                tasks.append(asyncio.create_task(get_voice_messages(client, dialog.id)))
                await asyncio.sleep(0.5)  # 每次创建任务后延迟0.5秒
        except ValueError:
            continue
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 01:00:48