Python多进程multiprocessing共享数据Value(包括常用的整数、字符串)、列表及字典以及Queue

1. 共享Value、列表以及字典

import multiprocessing
import ctypes
import time


def process_write(int_data, str_data, list_data, dict_data):
i = 1
while True:
int_data.value = i
str_data.value = 'str' + str(i)
list_data[0] = i
dict_data['dict0'] = i
print('write, index: ', i)
i += 1

def process_read(int_data, str_data, list_data, dict_data):
while True:
print('read data: ', int_data.value, str_data.value, list_data[0], dict_data['dict0'])



if __name__=='__main__':
int_data = multiprocessing.Manager().Value(ctypes.c_int, 0)
str_data = multiprocessing.Manager().Value(ctypes.c_char_p, 'str0')

list_data = multiprocessing.Manager().list()
list_data.append(0)
dict_data = multiprocessing.Manager().dict()
dict_data['dict0'] = 0



p1 = multiprocessing.Process(target=process_write, args=(int_data, str_data, list_data, dict_data,))
p2 = multiprocessing.Process(target=process_read, args=(int_data, str_data, list_data, dict_data,))
p1.start()
p2.start()

start = time.time()
while time.time() - start < 1:
pass
p1.terminate()
p2.terminate()

 


执行结果部分截图如下图。

 

 

 

 

2. Queue
数据先存先取,所以最后取到的数据可能是先前的数据,数据不是实时的,代码和执行结果如下图。

import multiprocessing
import ctypes
import time


def process_write(queue):
i = 1
while True:
queue.put(i)
print('put data: ', i)
i += 1

def process_read(queue):
while True:
time.sleep(0.2)
print('read data: ', queue.get())
#print('read data: ', queue.get_nowait())
print('get data wait end\n')



if __name__=='__main__':
queue = multiprocessing.Manager().Queue()

p1 = multiprocessing.Process(target=process_write, args=(queue,))
p2 = multiprocessing.Process(target=process_read, args=(queue,))
p1.start()
p2.start()

start = time.time()
while time.time() - start < 5:
pass
p1.terminate()
p2.terminate()

 

 


每次从queue中get数据时,都得等待queue有数据,也就是先执行put,再执行get。如果queue为空,直接使用get_nowait()方法取数据,那么抛异常,如下图。

 

 

 

 

 

 

 

3. 总结
3.1 对于先进先出的需求,取完前面的数据后,才能取后面的数据,这种场景使用Queue类,而且适用于更新数据进程比获取数据进程快,否则获取数据进程需要等待更新数据进程。

3.2 对于一般进程间共享数据来说,使用multiprocessing.Manager().Value和multiprocessing.Manager().list()和multiprocessing.Manager().dict()即可。

3.3 Value传递其它类型的参数对应表。

 

 

 

 

 

 

附录 使用multiprocessing.Value而不是multiprocessing.Manager().Value引起的问题

import multiprocessing
import ctypes
import time


def process_write(val):
i = 1
while True:
val.value = ("str" + str(i)).encode('utf-8')
print('write index: ', i)
i += 1

def process_read(val):
while True:
print('read data: ', val.value)



if __name__=='__main__':
val = multiprocessing.Value(ctypes.c_char_p, "str0".encode('utf-8'))

p1 = multiprocessing.Process(target=process_write, args=(val,))
p2 = multiprocessing.Process(target=process_read, args=(val,))
p1.start()
p2.start()

start = time.time()
while time.time() - start < 1:
pass
p1.terminate()
p2.terminate()

 


附录1 错误:bytes or integer address expected instead of str instance


原因及解决方案:使用Value传递参数,和C函数接口有关,涉及类型转换。将字符串编码为utf-8,在字符串后面加上 .encode('utf-8'),如下图。

 

 

 

 

 

附录2 写进程正常工作,但是程序没有抛异常就强制停止

 

 


通过定位,发现是使用val.value获取数据有误,思考过后,可能是觉得对象读写发生冲突,于是想着使用copy包的copy方法进行克隆,然后再使用,结果报错如下。

 

 

 

 

经过搜索,才发现直接使用multiprocessing.Value是线程不安全的,需要使用multiprocessing.Manager().Value才行,所以更改即可。

 

 

 

 



原文链接:https://blog.csdn.net/yldmkx/article/details/115948722

posted @ 2022-08-25 09:41  超级宝宝11  阅读(2284)  评论(0编辑  收藏  举报