最近用python (3.10的版本) 来写一个读取共享内存的程序,发现每次程序退出后会自动把这个共享内存给删掉,而实际没有调用任何close或del的方法,查阅了下资料,发现了如下bug:
具体代码如下:
from multiprocessing import shared_memory,resource_tracker
shm_name = '/test_share'
shm = shared_memory.SharedMemory(name=shm_name,create=False)
resource_tracker.unregister(f'/{shm_name}', "shared_memory")
注:要在共享名称前还要加个符号/
注:使用PyInstaller打包运行会存在问题(可能跟resource_tracker有关),使用nuikta打包不会
恰好笔者有程序需要用pyinstaller打包,后来研究了一下,放弃使用这个python自带的shared_memory,改为直接使用ctypes访问shared memory的api, 具体代码可参考如下:
import ctypes
import mmap
import os
import stat
import sys
try:
unicode
except NameError:
unicode = str
rtld = ctypes.cdll.LoadLibrary(None)
_shm_open = rtld.shm_open
_shm_unlink = rtld.shm_unlink
def shm_open(name):
if isinstance(name, bytes):
name = ctypes.create_string_buffer(name)
elif isinstance(name, unicode):
name = ctypes.create_unicode_buffer(name)
else:
raise TypeError("`name` must be `bytes` or `unicode`")
result = _shm_open(
name,
ctypes.c_int(os.O_RDWR | os.O_CREAT | os.O_EXCL),
ctypes.c_ushort(stat.S_IRUSR | stat.S_IWUSR)
)
if result == -1:
raise RuntimeError(os.strerror(ctypes.get_errno()))
return result
def shm_unlink(name):
if isinstance(name, bytes):
name = ctypes.create_string_buffer(name)
elif isinstance(name, unicode):
name = ctypes.create_unicode_buffer(name)
else:
raise TypeError("`name` must be `bytes` or `unicode`")
result = _shm_unlink(name)
if result == -1:
raise RuntimeError(os.strerror(ctypes.get_errno()))
代码来源:https://gist.github.com/jakirkham/100a7f5e86b0ff2a22de0850723a4c5c
用这个替换后,pyinstaller打包的程序是正常的。