Python基础_多进程数据共享
- 一、多进程数据共享
- 二、使用multiprocessing.Manager对象
- 三、使用multiprocessing.Value和multiprocessing.Array
- 四、使用管道和队列
- 五、使用共享内存
- 六、注意事项
一、多进程数据共享
Python中,多进程之间的数据共享是一个复杂的主题,因为每个进程都有自己的内存空间和独立的Python解释器实例。这意味着它们不能直接共享数据,就像线程那样。但是,Python提供了几种方法来间接地实现多进程之间的数据共享。
二、使用multiprocessing.Manager对象
multiprocessing
模块提供了一个Manager
对象,它可以让创建可以在多个进程之间共享的数据结构,如列表和字典。Manager
对象背后实际上是通过进程间通信(IPC)实现的。
**使用示例:**创建可以在多个进程之间共享的字典
from multiprocessing import Process, Manager
def func(d, i):
d[i] = i * i
if __name__ == '__main__':
with Manager() as manager:
d = manager.dict()
processes = [Process(target=func, args=(d, i)) for i in range(10)]
for p in processes:
p.start()
for p in processes:
p.join()
print(d)
# 执行结果
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
三、使用multiprocessing.Value和multiprocessing.Array
这两个类允许创建可以在多个进程之间共享的值和数组。
它们是基于ctypes
模块的,这意味着可以创建不同类型的数据结构(如整数、浮点数数组等)。
**使用示例:**使用共享类Value
、Array
from multiprocessing import Process, Value, Array
def func(n, a):
n.value = 3.1415927
for i in range(len(a)):
a[i] **= 2
if __name__ == '__main__':
num = Value('d', 0.0)
arr = Array('i', range(10))
p = Process(target=func, args=(num, arr))
p.start()
p.join()
print(num.value)
print(arr[:])
# 执行结果
3.1415927
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
四、使用管道和队列
尽管不是真正的“共享”数据,但multiprocessing.Pipe
和multiprocessing.Queue
提供了进程间通信的机制。
这些对象可以在进程之间传递数据,从而实现某种形式的数据“共享”。
使用示例:Queue
数据共享
from multiprocessing import Process, Queue
def func(q, i):
q.put('hello {} times'.format(i))
if __name__ == '__main__':
q = Queue()
plist= [Process(target=func, args=(q, i)) for i in range(3)]
for p in plist:
p.start()
p.join()
while not q.empty():
tmpVal = q.get()
print(tmpVal)
# 执行结果
hello 0 times
hello 1 times
hello 2 times
五、使用共享内存
在某些情况下,可能需要直接使用操作系统的共享内存机制。可以通过multiprocessing.RawValue
和multiprocessing.RawArray
类来实现,但它们提供了更低的抽象级别,需要谨慎使用。
multiprocessing.RawValue
和 multiprocessing.RawArray
用于创建可以直接在多个进程之间共享的内存区域。
与 Manager
、Value
和 Array
不同,RawValue
和 RawArray
不提供任何锁机制,因此它们更快,但同时也需要程序员负责同步以避免数据竞争。
使用 RawValue
和 RawArray
示例:
from multiprocessing import Process, RawValue, RawArray, Lock
# 使用RawValue
def process_with_raw_value(value, lock):
with lock:
for _ in range(10000): # 假设有很多次写操作
value.value += 1
# 使用RawArray
def process_with_raw_array(arr, lock):
with lock:
for i in range(len(arr)):
arr[i] **= 2 # 对数组中的每个元素进行平方操作
if __name__ == '__main__':
# 创建一个RawValue对象,初始值为0,类型为'i'(整数)
lock = Lock() # 创建一个锁对象用于同步
shared_value = RawValue('i', 0)
# 创建一个RawArray对象,包含5个整数元素
shared_array = RawArray('i', [1, 2, 3, 4, 5])
# 创建并启动两个进程,分别处理RawValue和RawArray
p1 = Process(target=process_with_raw_value, args=(shared_value, lock))
p2 = Process(target=process_with_raw_array, args=(shared_array, lock))
p1.start()
p2.start()
p1.join()
p2.join()
# 由于RawValue和RawArray不提供同步机制,们需要使用锁来确保数据一致性
with lock:
print("Shared value:", shared_value.value) # 输出共享值的最终结果
print("Shared array:", shared_array[:]) # 输出共享数组的最终结果
# 执行结果
Shared value: 10000
Shared array: [1, 4, 9, 16, 25]
注意:尽管 RawValue
和 RawArray
提供了更高的性能和更灵活的数据共享方式,但它们也更难正确使用,因为需要程序员自己处理所有的同步问题。在大多数情况下,如果不需要这么底层的控制,使用 Manager
、Value
或 Array
会更简单和安全。
六、注意事项
由于GIL(全局解释器锁)的存在,共享数据在并发修改时可能会导致不可预知的行为。
因此,在共享数据时,请务必确保正确地同步进程,以避免数据竞争和不一致。
may the odds be ever in your favor ~
标签:__,RawValue,Python,value,RawArray,Process,数据共享,进程,multiprocessing From: https://blog.csdn.net/weixin_36928396/article/details/136632023