shared_memory.sharedmemory创建后不会自动释放,必须由创建者显式调用close()断开连接、unlink()销毁系统资源,否则残留导致fileexistserror或内存泄漏。

shared_memory.SharedMemory 创建后必须手动释放
Python 3.8+ 的 shared_memory 模块不是“即用即走”的封装,SharedMemory 实例创建后会占用系统共享内存段(Linux/macOS 下是 /dev/shm 中的文件,Windows 下是命名内存映射对象),**不显式调用 close() 和 unlink() 就不会释放**。常见错误是进程退出前忘记 unlink(),导致残留段堆积,下次运行时可能报 FileExistsError: [Errno 17] File exists。
实操建议:
-
unlink()只能由创建者(即调用SharedMemory(create=True)的进程)调用,其他进程只能close() - 推荐用
try/finally或上下文管理器(但注意:原生SharedMemory不支持with,需自行包装) - 示例释放逻辑:
shm = SharedMemory(create=True, size=1024) try: # 使用 shm.buf pass finally: shm.close() if hasattr(shm, '_name') and shm._name: # 确保是创建者 shm.unlink()
用 numpy.ndarray 绑定 shared_memory 的 buf 需对齐 dtype 和 shape
共享内存本身只是字节缓冲区(shm.buf),要当数组用,必须用 numpy.ndarray 以指定 dtype、shape 和 strides 重新解释这块内存。**最常踩的坑是 shape/dtype 不匹配导致读写越界或数据错乱**。
关键点:
-
dtype必须是 numpy 的固定大小类型(如np.float64、np.int32),不能用object或可变长字符串 -
shape计算出的总字节数不能超过shm.size;例如shape=(1000,), dtype=np.float64需要1000 * 8 = 8000字节 - 绑定方式必须用
np.ndarray(shape, dtype=dtype, buffer=shm.buf),不能用np.array(..., copy=False)—— 后者会复制,不共享 - 多维数组要小心 C/Fortran order,默认 C-order,
strides由shape和dtype自动推导,一般无需手设
子进程访问同一 shared_memory 需传入 name 而非对象
multiprocessing 的子进程无法直接继承父进程的 SharedMemory 对象(对象本身不序列化),**必须把 shm.name 作为参数传给子进程,再在子进程中用该 name 重新 attach**。传错 name 或拼写错误会导致 FileNotFoundError。
安全 Python 代码沙箱:在隔离的沙箱中执行任意 Python 代码,预装 requests、NumPy、pandas 库。返回 stdout、stderr。
典型协作模式:
- 主进程创建:
shm = SharedMemory(create=True, size=...),记录shm.name - 启动子进程时,把
shm.name和必要元信息(如shape,dtype)一起传入 - 子进程中:
shm_child = SharedMemory(name=received_name),再用同样shape/dtype构造ndarray - 所有进程结束后,仅创建者调用
shm.unlink()
注意:Windows 下 name 区分大小写,Linux/macOS 下不区分,但统一用小写更稳妥。
shared_memory 不提供同步机制,数组读写需额外加锁
shared_memory 只负责内存共享,**不包含任何原子操作或锁**。多个进程同时写同一数组区域会引发竞态条件,结果不可预测(比如两个进程同时执行 a[0] += 1,可能只生效一次)。
解决方案有限且需谨慎:
- 用
multiprocessing.Lock或mp.Semaphore控制临界区,但锁对象本身不能跨进程共享,需在主进程创建后传入子进程 - 避免频繁细粒度更新;尽量设计成“主进程写 + 子进程只读”,或按索引分区(如进程 i 只写
a[i::n]) - 不要依赖
numpy的 ufunc(如np.add.at)实现线程安全——它在共享内存上同样不安全 - 如果需要强一致性,考虑改用
multiprocessing.Array(底层带锁)或消息队列,而不是硬扛shared_memory
真正麻烦的地方不在创建和绑定,而在于生命周期管理和并发控制——name 忘记传、unlink 忘记调、锁没加对,任何一个都会让程序间歇性崩溃或静默出错。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










