asyncore 和 asynchat 在 python 3.12+ 中已被彻底移除,自 3.6 起标记为 deprecated;其基于 select 的过时 i/o 模型不支持 tls、http/2 等现代特性,且无法与 asyncio 兼容,应改用 asyncio.streamreader/streamwriter 替代。

asyncore 和 asynchat 在 Python 3.12+ 中已被正式移除,官方文档明确标记为 deprecated 自 3.6 起,3.12 彻底删除。直接用它们写新服务会失败:运行时抛出 ModuleNotFoundError: No module named 'asyncore'。
别再查旧教程拼凑代码——你看到的示例(比如 EchoHandler 继承 asynchat.async_chat)在现代 Python 上根本跑不起来。
为什么 asyncore/asynchat 不再可用
这两个模块依赖过时的低层 I/O 模型(基于 select + 阻塞 socket 的非阻塞封装),缺乏对 TLS、HTTP/2、连接池、超时精细控制等现代需求的支持。CPython 团队早在 PEP 492(async/await)落地后就启动了淘汰流程。
-
asyncore.loop()无法与asyncio事件循环共存,强行混合会导致调度冲突或静默卡死 -
asynchat.async_chat.set_terminator(b"\r\n")这类字符串分割逻辑,在二进制协议或粘包场景下极易出错,且无内置重试/粘包缓冲管理 - 所有
handle_*()方法(如handle_read)都是同步回调,无法await任何异步操作(比如查数据库、调 API)
替代方案:用 asyncio 写等效功能
你需要的是「按分隔符收消息」+「连接生命周期管理」,asyncio.StreamReader + asyncio.StreamWriter 可直接替代 asynchat 的核心能力,且更健壮。
-
reader.readuntil(b"\r\n")精确替代set_terminator(b"\r\n")+found_terminator() -
reader.readexactly(n)替代整数长度 terminator 场景 -
writer.write(data)+await writer.drain()替代push(),并自动处理背压 - 异常直接用
try/except捕获,不用重写handle_error
示例片段:
async def handle_client(reader, writer):
while True:
try:
line = await reader.readuntil(b"\r\n")
# line 包含 \r\n,需 .rstrip(b"\r\n")
writer.write(line) # 回显
await writer.drain()
except asyncio.IncompleteReadError:
break # 客户端断开
except ConnectionResetError:
break
迁移时最容易忽略的细节
旧代码里看似简单的 self.data.append(data) 在 asyncio 下必须变成显式缓冲管理——因为 readuntil() 自动切分,但 read(1024) 可能截断 terminator。若协议允许任意长度前缀(如 LEN\r\nPAYLOAD),你得自己用 reader.readexactly() 先读长度,再读 payload,中间不能穿插其他 await,否则状态丢失。
另外:asyncore.dispatcher.close() 是立即释放 socket,而 writer.close() 只是标记关闭,必须跟 await writer.wait_closed() 才算真正清理完毕——漏掉这一步,连接可能 linger 在 CLOSE_WAIT 状态。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











