Windows下Python多进程TCP客户端偶发创建失败问题求助
Windows下Python多进程传递Socket引发的不稳定进程创建问题
问题描述
在Windows 10 + Python 3.11.2环境下,搭建了如下架构:
- TCP服务器通过新线程处理 incoming connections,
listen的backlog设置为200 - 另一个进程通过
multiprocessing.Process创建大量TCP客户端进程连接服务器
但客户端进程创建不稳定:有时5个就出错,有时150个正常运行,部分进程创建失败,报错如下:
Traceback (most recent call last): File "<string>", line 1, in <module> File "C:\Users\erath\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\spawn.py", line 120, in spawn_main exitcode = _main(fd, parent_sentinel) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\erath\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\spawn.py", line 130, in _main self = reduction.pickle.load(from_parent) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\erath\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\reduction.py", line 238, in _rebuild_socket return ds.detach() ^^^^^^^^^^^ File "C:\Users\erath\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\resource_sharer.py", line 38, in detach with _resource_sharer.get_connection(self._id) as conn: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\erath\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\resource_sharer.py", line 86, in get_connection c = Client(address, authkey=process.current_process().authkey) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\erath\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\connection.py", line 499, in Client c = PipeClient(address) ^^^^^^^^^^^^^^^^^^^ File "C:\Users\erath\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\connection.py", line 701, in PipeClient _winapi.WaitNamedPipe(address, 1000) FileNotFoundError: [WinError 2] Das System kann die angegebene Datei nicht finden
问题原因
Windows平台下Python的多进程默认使用spawn启动方式:
- spawn模式会启动一个全新的Python解释器进程,而非类Unix系统的fork方式
- 父进程需要将传递给子进程的对象序列化(pickle),子进程再反序列化重建对象
- 对于Socket这类操作系统级资源,序列化时依赖
multiprocessing.resource_sharer通过**命名管道(Named Pipe)**共享文件描述符 - 当父进程短时间内创建大量子进程时,命名管道的创建/初始化速度跟不上子进程启动节奏,或者父进程的资源共享服务被抢占,导致子进程尝试连接命名管道时找不到资源,抛出
FileNotFoundError
解决方案
最可靠的修复方式是不在父进程创建Socket传递给子进程,而是让每个子进程自行创建Socket,彻底避免跨进程传递操作系统资源的问题。
修改后的客户端代码:
import socket import multiprocessing import time MAX_DATASIZE = 2048 HOST = "127.0.0.1" PORT = 5000 def handleSingleConnection(i): # 子进程内部创建Socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((HOST, PORT)) time.sleep(2) sock.sendall(f"Hello from Process {i}!".encode()) result = sock.recv(MAX_DATASIZE) print(result) sock.close() if __name__ == '__main__': processes = [] for i in range(150): process = multiprocessing.Process(target=handleSingleConnection, args=(i,)) process.start() processes.append(process) # 可选:等待所有子进程结束,避免父进程提前退出导致资源泄漏 for p in processes: p.join()
额外优化建议
- 父进程通过
join()等待所有子进程完成,避免父进程提前终止引发资源清理异常 - 若需要控制并发连接数,可使用进程池(
multiprocessing.Pool)替代循环创建进程,避免短时间内创建过多进程引发系统资源竞争
内容的提问来源于stack exchange,提问作者derkirgise
相关产品推荐
相关产品推荐

