You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python3 multiprocessing SharedMemory 重连已有共享内存失败问题

问题描述

我想实现的操作是:先运行testb.py创建共享内存,再运行testc.py连接该共享内存;关闭testc.py后重新运行,再次连接共享内存,但最后一步遇到问题。简单来说,我希望在长生命周期的代码中创建共享内存,供不同进程连接,但进程结束重启后出现异常。

相关代码

testa.py

from multiprocessing.shared_memory import SharedMemory


class CommonDataHandler:
    def __init__(self) -> None:
        self.check_init()

    def check_init(self):
        try:
            self.shared_data_shm = SharedMemory(name='integer', create=False)
        except FileNotFoundError:
            self.create_shared_objects()

    def get_value(self):
        return int.from_bytes(self.shared_data_shm.buf[:4], byteorder='little')
    
    def set_value(self, value):
        self.shared_data_shm.buf[:4] = value.to_bytes(4, byteorder='little')

    def create_shared_objects(self):
        # 创建共享内存
        self.shared_data_shm = SharedMemory(name='integer', create=True, size=4)
        # 初始化默认值
        value = 11
        # 将数据写入共享内存缓冲区
        self.shared_data_shm.buf[:4] = value.to_bytes(4, byteorder='little')
        print("共享对象已创建。")

    def disconnect(self):
        self.shared_data_shm.close()
        print("共享对象已断开连接。")

    def cleanup(self):
        self.shared_data_shm.unlink()
        print("共享对象已解除链接。")

testb.py

from testa import CommonDataHandler
from time import time, sleep

st = time()
c = CommonDataHandler()
print(f"CommonDataHandler in testb: {time()-st:.6f} seconds")

for i in range(10):
    value = c.get_value()
    print(f"Value: {value}")
    c.set_value(i)
    sleep(1)

c.cleanup()

testc.py

from testa import CommonDataHandler
from time import time, sleep
import os

st = time()
c = CommonDataHandler()
print(f"CommonDataHandler in testc: {time()-st:.6f} seconds")

print(f"Value: {c.get_value()}")

c.disconnect()

# sleep(1)
# os.system("python3 testc.py")

运行输出

终端1运行testb.py:

py testb.py
共享对象已创建。
CommonDataHandler in testb: 0.000350 seconds
Value: 11
Value: 0
Value: 1
Value: 2
Value: 3
Value: 4
Value: 5
Value: 6
Value: 7
Value: 8
共享对象已解除链接。

终端2首次运行testc.py:

CommonDataHandler in testc: 0.000304 seconds
Value: 1
共享对象已断开连接。

同时弹出警告:

/usr/lib/python3.10/multiprocessing/resource_tracker.py:224: UserWarning: resource_tracker: There appear to be 1 leaked shared_memory objects to clean up at shutdown
warnings.warn('resource_tracker: There appear to be %d '

终端2再次运行testc.py:

共享对象已创建。
CommonDataHandler in testc: 0.000390 seconds
Value: 11
共享对象已断开连接。

同样出现上述资源泄漏警告。

取消testc.py中注释行后的运行结果:

CommonDataHandler in testc: 0.000314 seconds
Value: 1
共享对象已断开连接。
CommonDataHandler in testc: 0.000280 seconds
Value: 2
共享对象已断开连接。
CommonDataHandler in testc: 0.000313 seconds
Value: 3
共享对象已断开连接。
CommonDataHandler in testc: 0.000330 seconds
Value: 4
共享对象已断开连接。
CommonDataHandler in testc: 0.000317 seconds
Value: 5
共享对象已断开连接。
CommonDataHandler in testc: 0.000325 seconds
Value: 6
共享对象已断开连接。
CommonDataHandler in testc: 0.000295 seconds
Value: 7
共享对象已断开连接。
CommonDataHandler in testc: 0.000302 seconds
Value: 8
共享对象已断开连接。
CommonDataHandler in testc: 0.000307 seconds
Value: 9
共享对象已断开连接。
共享对象已创建。
CommonDataHandler in testc: 0.000375 seconds
Value: 11
共享对象已断开连接。

问题原因与解决方法

核心问题

  1. 共享内存被提前销毁:testb.py运行结束时调用cleanup()执行unlink(),直接销毁了共享内存,导致后续testc.py重启后找不到原内存,只能重新创建并读取初始值11。
  2. 资源泄漏警告:虽然testc.py调用了disconnect()关闭共享内存,但Python的resource_tracker可能因进程退出时的资源清理顺序问题,误报资源泄漏。

解决步骤

1. 让共享内存长期存活

修改testb.py,不在进程结束时销毁共享内存,改为手动控制销毁时机:

# 修改后的testb.py
from testa import CommonDataHandler
from time import time, sleep

st = time()
c = CommonDataHandler()
print(f"CommonDataHandler in testb: {time()-st:.6f} seconds")

for i in range(10):
    value = c.get_value()
    print(f"Value: {value}")
    c.set_value(i)
    sleep(1)

# 仅断开连接,不销毁共享内存
c.disconnect()
# 等待用户输入后再销毁
print("共享内存保持存活,按任意键销毁...")
input()
c.cleanup()

2. 自动释放资源避免警告

在testa.py的CommonDataHandler类中添加__del__方法,确保对象被回收时自动关闭共享内存:

# 在CommonDataHandler类中新增
def __del__(self):
    if hasattr(self, 'shared_data_shm'):
        self.shared_data_shm.close()

3. 防止重复创建共享内存

如果需要确保只有一个进程创建共享内存,可添加文件锁等同步机制,避免多进程同时触发创建逻辑。

验证效果

  • 运行修改后的testb.py,循环结束后共享内存仍保持存活,多次运行testc.py都能连接到同一内存并读取最新值。
  • 按下testb.py的输入键后,共享内存被销毁,后续testc.py会重新创建。

内容的提问来源于stack exchange,提问作者Alperen Ölçer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 14:52:36