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

向共享内存列表复制bytes对象时尾部零被截断的原因及解决办法

问题:ShareableList赋值时丢失bytes尾部零字节

我尝试将大型bytes对象复制到已用足够大的bytes对象初始化的可共享列表(ShareableList)中。当待复制的bytes对象存在尾部零(即末尾值为0x00)时,共享内存列表中的新条目会丢失这些零,而数据中间的零不会导致提前截断。以下是包含输出的最简示例:

示例代码

from multiprocessing import shared_memory as shm

shmList = shm.ShareableList([bytes(50)])
testBytes = bytes.fromhex("00112233445566778899aabbccddeeff0000")

shmList[0] = testBytes
print(testBytes)
print(shmList[0])

shmList.shm.close()
shmList.shm.unlink()

运行输出

b'\x00\x11"3DUfw\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x00\x00'
b'\x00\x11"3DUfw\x88\x99\xaa\xbb\xcc\xdd\xee\xff'

我原本期望bytes对象能完整复制,包括尾部零。这似乎是一个“特性”,但为什么会这样?有没有简单的解决办法?


解答

原因分析

这是因为ShareableList在读取bytes类型数据时,依赖了ctypes.string_at函数——这个函数会把共享内存中的数据当作以\x00结尾的C风格字符串处理,读取时会自动截断到第一个末尾\x00的位置,所以尾部的零字节会被丢弃。

实际上写入共享内存时数据是完整的,但读取逻辑的截断规则导致尾部零被忽略。

解决办法

这里提供两种简单可行的方案:

方案1:固定长度填充与截取

利用ShareableList初始化时的固定长度,赋值时将目标bytes填充到该长度(不足补零),读取时再截取原始数据的真实长度:

from multiprocessing import shared_memory as shm

init_length = 50
shmList = shm.ShareableList([bytes(init_length)])
testBytes = bytes.fromhex("00112233445566778899aabbccddeeff0000")

# 将数据填充到初始化的固定长度,确保尾部零被保留在共享内存中
shmList[0] = testBytes.ljust(init_length, b'\x00')
# 读取时截取原始数据的长度,还原完整bytes
retrieved_data = shmList[0][:len(testBytes)]

print(testBytes)
print(retrieved_data)

shmList.shm.close()
shmList.shm.unlink()

方案2:直接使用SharedMemory类

如果不需要列表结构,直接使用底层的SharedMemory类完全控制读写逻辑,避开C字符串的截断限制:

from multiprocessing import shared_memory as shm

testBytes = bytes.fromhex("00112233445566778899aabbccddeeff0000")

# 创建刚好容纳数据的共享内存块
shm_block = shm.SharedMemory(create=True, size=len(testBytes))
# 直接写入字节数据
shm_block.buf[:len(testBytes)] = testBytes
# 读取完整的字节数据
retrieved_data = bytes(shm_block.buf[:len(testBytes)])

print(testBytes)
print(retrieved_data)

shm_block.close()
shm_block.unlink()

内容的提问来源于stack exchange,提问作者Reid Pinkham

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 17:32:51