python多进程multiprocessing.sharedctypes模块的共享内存问题

最近涉及到三个进程互相通信,使用了共享内存传递参数,所以记录一下,以备以后查阅。

有两种函数:sharedctypes.Array() & sharedctypes.RawArray()
定义一个共享内存变量:
这是存储一个1*2数组的变量,存储float类型的x,y值

xy_arr = sharedctypes.Array(ctypes.c_float, 1*2, lock=False)
或者:
xy_arr = sharedctypes.RawArray(ctypes.c_float, 1*2)

此时:

print("xy_det:", type(xy_arr))
输出结果:
xy_det: <class 'multiprocessing.sharedctypes.c_float_Array_2'>
即可对它进行赋值运算

需要注意的是,如果使用Array函数设置共享内存变量,缺少lock参数,或其值为True,则赋值时会报错:

xy_arr = sharedctypes.Array(ctypes.c_float, 1*2, lock=True)
或
xy_arr = sharedctypes.Array(ctypes.c_float, 1*2)

会报以下错误:

print("xy_det:", type(xy_arr))
输出结果:
xy_det: <class 'multiprocessing.sharedctypes.SynchronizedArray'>

TypeError: a bytes-like object is required, not 'SynchronizedArray'

所以 sharedctypes.Array() & sharedctypes.RawArray() 内的参数不能混用


附录官方手册的函数说明:

multiprocessing.sharedctypes 模块

multiprocessing.sharedctypes 模块提供了一些函数,用于分配来自共享内存的、可被子进程继承的 ctypes 对象。

注解 虽然可以将指针存储在共享内存中,但请记住它所引用的是特定进程地址空间中的位置。 而且,指针很可能在第二个进程的上下文中无效,尝试从第二个进程对指针进行解引用可能会导致崩溃。


multiprocessing.sharedctypes.RawArray(typecode_or_type, size_or_initializer)

从共享内存中申请并返回一个 ctypes 数组。

typecode_or_type 指明了返回的数组中的元素类型: 它可能是一个 ctypes 类型或者 array 模块中使用的类型字符。 如果 size_or_initializer 是一个整数,那就会当做数组的长度,并且整个数组的内存会初始化为0。否则,如果 size_or_initializer 会被当成一个序列用于初始化数组中的每一个元素,并且会根据元素个数自动判断数组的长度。

注意对元素的访问、赋值操作可能是非原子操作 - 使用 Array() , 从而借助其中的锁保证操作的原子性。


multiprocessing.sharedctypes.RawValue(typecode_or_type, *args)

从共享内存中申请并返回一个 ctypes 对象。

typecode_or_type 指明了返回的对象类型: 它可能是一个 ctypes 类型或者 array 模块中每个类型对应的单字符长度的字符串。 *args 会透传给这个类的构造函数。

注意对 value 的访问、赋值操作可能是非原子操作 - 使用 Value() ,从而借助其中的锁保证操作的原子性。

请注意 ctypes.c_char 的数组具有 value 和 raw 属性,允许被用来保存和提取字符串 - 请查看 ctypes 文档。


multiprocessing.sharedctypes.Array(typecode_or_type, size_or_initializer, *, lock=True)

返回一个纯 ctypes 数组, 或者在此之上经过同步器包装过的进程安全的对象,这取决于 lock 参数的值,除此之外,和 RawArray() 一样。

如果 lock 为 True (默认值) 则将创建一个新的锁对象用于同步对值的访问。 如果 lock 为一个 Lock 或 RLock 对象则该对象将被用于同步对值的访问。 如果 lock 为 False 则对所返回对象的访问将不会自动得到锁的保护,也就是说它将不是“进程安全的”。

注意 lock 只能是命名参数。


multiprocessing.sharedctypes.Value(typecode_or_type, *args, lock=True)

返回一个纯 ctypes 数组, 或者在此之上经过同步器包装过的进程安全的对象,这取决于 lock 参数的值,除此之外,和 RawArray() 一样。

如果 lock 为 True (默认值) 则将创建一个新的锁对象用于同步对值的访问。 如果 lock 为一个 Lock 或 RLock 对象则该对象将被用于同步对值的访问。 如果 lock 为 False 则对所返回对象的访问将不会自动得到锁的保护,也就是说它将不是“进程安全的”。

注意 lock 只能是命名参数。