这是一个在 Python 网络编程历史上非常重要的模块,但现在已经不推荐在新项目中使用,理解它对于学习网络编程的历史和演进非常有帮助。

asyncore 是什么?
asyncore 是 Python 标准库中的一个模块,它提供了一个基于事件驱动的异步网络编程框架,它的核心思想是让一个单线程能够同时处理多个网络连接(I/O多路复用)。
在 asyncore 出现之前,处理多个客户端连接通常需要为每个连接创建一个线程(多线程模型)或一个进程(多进程模型),这两种模型在高并发场景下都存在性能瓶颈(线程/进程创建和切换的开销)。
asyncore 通过I/O多路复用技术(如 select、poll、epoll 等)解决了这个问题,它允许你在一个循环中监视多个网络套接字(socket),当任何一个套接字准备好进行读、写或处理错误时,框架会通知你,然后你就可以对这个特定的套接字进行相应的处理。
核心概念和工作原理
asyncore 的工作流程非常清晰:

- 创建
dispatcher子类:你需要创建一个继承自asyncore.dispatcher的类,这个类代表了你的网络连接(无论是服务器还是客户端)。 - 实现事件处理方法:在你的
dispatcher子类中,你需要重写一些特定方法来处理网络事件,当某个事件发生时,asyncore会自动调用你的这些方法。handle_read():当套接字准备好读取数据时被调用。handle_write():当套接字准备好写入数据时被调用。handle_connect():当客户端成功连接到服务器时被调用。handle_accept():当服务器接受一个新连接时被调用(仅用于服务器)。handle_close():当连接关闭时被调用。handle_error():当发生错误时被调用。
- 创建实例并启动事件循环:创建你的
dispatcher实例(创建一个服务器监听套接字或客户端连接套接字),然后调用asyncore.loop()启动主事件循环,这个循环会一直阻塞,直到所有的连接都关闭。
asyncore.loop() 内部会使用 select 系统调用来监视所有已注册的套接字,并根据它们的状态(可读、可写、异常)来调用相应的事件处理方法。
一个简单的 asyncore 服务器示例
下面是一个完整的、简单的回显服务器(Echo Server)的例子,它会监听一个端口,并将接收到的任何消息原样发送回去。
import asyncore
import socket
class EchoHandler(asyncore.dispatcher):
"""处理单个客户端连接的类"""
def __init__(self, sock):
# asyncore.dispatcher.__init__ 会将传入的 sock 设置为套接字
super().__init__(sock)
self.data_to_send = b"Welcome to the Echo Server!\n"
def handle_read(self):
"""当套接字可读时被调用"""
try:
# 接收数据
received_data = self.recv(1024)
if received_data:
print(f"Received: {received_data.decode().strip()}")
# 将接收到的数据添加到待发送队列
self.data_to_send += received_data
else:
# recv 返回空数据,表示客户端已关闭连接
print("Client closed connection.")
self.close()
except ConnectionResetError:
print("Client forcibly closed the connection.")
self.close()
def handle_write(self):
"""当套接字可写时被调用"""
if self.data_to_send:
# 发送数据
sent_bytes = self.send(self.data_to_send)
# 从待发送队列中移除已发送的部分
self.data_to_send = self.data_to_sent[sent_bytes:]
def handle_close(self):
"""当连接关闭时被调用"""
print("Closing connection.")
self.close()
class EchoServer(asyncore.dispatcher):
"""服务器类,用于接受新连接"""
def __init__(self, host, port):
super().__init__()
# 创建一个 TCP 套接字
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
# 允许地址重用,避免 "Address already in use" 错误
self.set_reuse_addr()
# 绑定地址和端口
self.bind((host, port))
# 开始监听, backlog 设为 5
self.listen(5)
def handle_accept(self):
"""当有新连接到来时被调用"""
# 接受新连接
pair = self.accept()
if pair is not None:
sock, addr = pair
print(f"Accepted connection from {addr}")
# 为新连接创建一个 EchoHandler 实例
handler = EchoHandler(sock)
if __name__ == "__main__":
print("Starting Echo Server on localhost:8080")
# 创建服务器实例
server = EchoServer('localhost', 8080)
# 启动事件循环
# loop() 会一直运行,直到没有活动的通道
asyncore.loop()
如何运行和测试:
- 保存上面的代码为
asyncore_server.py。 - 在一个终端运行它:
python asyncore_server.py,你会看到 "Starting Echo Server..." 的消息。 - 在另一个终端,使用
telnet或nc(netcat) 连接服务器:telnet localhost 8080
或者
(图片来源网络,侵删)nc localhost 8080
- 连接后,你会首先收到 "Welcome to the Echo Server!",然后你输入任何内容,服务器都会把它发回给你,断开连接后,服务器端会打印 "Closing connection."。
优点与缺点
优点
- 单线程高并发:能够在单个线程中高效处理成百上千个连接,避免了多线程/多进程的复杂性。
- 资源消耗低:相比为每个连接创建一个线程,
asyncore模型的内存和CPU开销要小得多。 - 模型简单:对于简单的应用,其基于回调的模型比较直观。
缺点 (这也是它被废弃的原因)
- 基于回调,代码难以维护:当逻辑变得复杂时,大量的回调函数(
handle_read,handle_write等)会导致代码难以阅读、调试和维护,这就是所谓的“回调地狱”(Callback Hell)。 - 错误处理不完善:错误处理机制比较脆弱,一个未捕获的异常可能会破坏整个事件循环。
- 功能陈旧:它使用的是最基础的
select多路复用技术,现代系统提供了更高效的epoll(Linux) 和kqueue(BSD/macOS),虽然asyncore内部会尝试使用最优的,但其整体架构已经过时。 - Python 3.10+ 已被移除:由于其设计上的缺陷和更现代替代方案的出现,
asyncore模块在 Python 3.10 中被正式移除。
现代替代方案
asyncore 的精神被更现代、更强大的异步框架所继承和发扬,如果你现在需要做异步网络编程,应该使用以下方案:
asyncio (Python 3.4+ 内置)
这是 Python 官方推荐的、现代的异步 I/O 框架,它使用 async/await 语法,彻底解决了回调地狱的问题,代码结构清晰,易于理解和维护。
asyncio 使用更高效的 epoll/kqueue 作为其后端,性能卓越。
使用 asyncio 重写上面的 Echo Server:
import asyncio
async def handle_echo(reader, writer):
data = await reader.read(100)
message = data.decode()
print(f"Received: {message.strip()}")
writer.write(data)
await writer.drain()
print("Closing connection.")
writer.close()
async def main():
server = await asyncio.start_server(handle_echo, '127.0.0.1', 8080)
addr = server.sockets[0].getsockname()
print(f'Serving on {addr}')
async with server:
await server.serve_forever()
if __name__ == "__main__":
asyncio.run(main())
对比一下,你会发现 asyncio 的代码更像同步代码,逻辑流更清晰。
第三方库
- Twisted:一个非常成熟和强大的事件驱动的网络框架,功能极其丰富,但学习曲线较陡峭。
- Tornado:由 Facebook 开发,最初是为了处理高并发下的实时服务(如聊天室),它也是一个功能强大的框架。
| 特性 | asyncore |
asyncio |
|---|---|---|
| Python 版本 | Python 2 & 3 (<= 3.9) | Python 3.4+ |
| 推荐状态 | 已废弃 | 官方推荐 |
| 编程模型 | 基于回调 | async/await 协程 |
| 代码可读性 | 差,易陷入回调地狱 | 优秀,接近同步代码 |
| 错误处理 | 脆弱 | 使用 try/except 块,健壮 |
| 核心机制 | select/poll |
epoll/kqueue/IOCP |
| 适用场景 | 遗留系统维护,学习历史 | 所有新的异步项目 |
asyncore 是 Python 异步网络编程的先驱,它成功地引入了事件驱动的思想,由于其设计上的局限性,它已经被 asyncio 所取代,对于任何新的 Python 项目,都应该学习和使用 asyncio 来构建高性能、可维护的异步网络应用,理解 asyncore 有助于你更好地理解异步编程的演进历程。
