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
相关产品推荐
相关产品推荐

