Python等待网络recv数据时如何执行其他命令/脚本,poll命令能否实现?
需求可行性结论
你的需求完全可以实现,这种场景属于阻塞IO场景下的并发调度经典需求,你提到的select.poll确实是符合要求的实现方案之一。
1 实现原理说明
默认情况下socket.recv()这类网络IO操作是阻塞调用,执行后当前线程会暂停运行直到收到数据,期间无法执行其他代码。要解决这个问题,常见有两类实现思路:
- 多线程/多进程方案:把阻塞的IO操作放到独立的子线程/子进程中运行,主线程继续执行其他业务逻辑
- IO多路复用方案:也就是你提到的
poll,同类型的还有select、epoll(Linux平台专属),不需要开启额外线程,单线程即可同时监听多个IO事件,等待IO就绪的间隙可以运行其他非阻塞逻辑
2 poll实现示例代码
以下是基于select.poll的最简可运行示例,实现等待recv数据的同时运行其他逻辑:
import socket import select # 初始化套接字并设置为非阻塞模式 server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_sock.setblocking(False) server_sock.bind(("127.0.0.1", 8080)) server_sock.listen(5) # 实例化poll对象 poll_obj = select.poll() # 注册服务端套接字的可读事件(POLLIN代表有数据可读/新连接接入) poll_obj.register(server_sock.fileno(), select.POLLIN) while True: # poll方法参数为超时时间,单位毫秒,设置为100表示每次最多等待100ms就返回 io_events = poll_obj.poll(100) if io_events: # 有IO事件触发,处理网络操作 for fd, event in io_events: if fd == server_sock.fileno() and event & select.POLLIN: client_sock, addr = server_sock.accept() client_sock.setblocking(False) poll_obj.register(client_sock.fileno(), select.POLLIN) print(f"新客户端接入:{addr}") elif event & select.POLLIN: # 执行recv读取数据 data = client_sock.recv(1024) if not data: poll_obj.unregister(fd) client_sock.close() continue print(f"收到客户端数据:{data.decode()}") else: # 无IO事件,等待超时,此处可以运行你需要执行的其他代码 print("等待网络数据中,执行其他业务逻辑...")
3 补充方案说明
如果你是入门开发者,觉得poll的底层操作太繁琐,也可以选择更简单的实现方案:
- 简单场景优先用
threading模块:将recv操作放到单独子线程中运行,不需要修改原有阻塞逻辑,代码写法更易理解 - 复杂高并发场景可以用
asyncio异步框架:底层封装了IO多路复用逻辑,语法更简洁,不需要手动管理poll的事件注册和监听
内容的提问来源于stack exchange,提问作者almostacoder
相关产品推荐
相关产品推荐

