简体   繁体   English

在python中使用多处理的共享对象数组

[英]Shared array of objects using multiprocessing in python

I am trying to create an array of shared objects (instances of a class) between different processes in a python program. 我试图在python程序中的不同进程之间创建一个共享对象(类的实例)的数组。 Each of these objects would be modified in the program. 这些对象中的每一个都将在程序中进行修改。 For this purpose I am using multiprocessing as follows: 为此,我使用多处理如下:

import multiprocessing
import numpy as np
sh = multiprocessing.RawArray (ctypes.py_object, 10)
f = np.frombuffer(sh, dtype=object)

and the error I get is: 我得到的错误是:

Traceback (most recent call last):
  File "<pyshell#14>", line 1, in <module>
    f = np.frombuffer(sh, dtype=object)
ValueError: cannot create an OBJECT array from memory buffer

Now my question is, first of all, is this generally the right way to tackle this problem, and second, what is my mistake in the above code? 现在我的问题是,首先,这通常是解决这个问题的正确方法,其次,我在上面的代码中的错误是什么? Thank you in advance. 先感谢您。

ctypes.py_object represents a PyObject * in C. It is a pointer to a struct that represents a Python object, resides in the private memory of the process, and contains more pointers. ctypes.py_object表示C中的PyObject * 。它是一个指向struct的指针,表示Python对象,驻留在进程的私有内存中,并包含更多指针。 Another process can't access it; 另一个进程无法访问它; trying to share a pointer between processes is not useful. 尝试在进程之间共享指针是没有用的。

See also this answer by Alex Martelli . 请参阅Alex Martelli的回答

You might want to use a multiprocessing.Queue , in which you can just dump objects without worrying about types. 您可能希望使用multiprocessing.Queue ,您可以在其中转储对象而无需担心类型。 It's also thread-safe and process-safe. 它还具有线程安全性和过程安全性。

Here's a simple example of a Queue used to facilitate the Producer-Consumer problem ( original source , Pizzas were a little bonus by me). 这是一个简单的Queue用于促进生产者 - 消费者问题的例子( 原始来源 ,Pizzas是我的一点奖励)。

from multiprocessing import Process, Queue

class Pizza(object):
    def __init__(self, pizza_num):
        self.pizza_num = pizza_num
        self.num_slices = 8

sentinel = "NO PIZZA"

def producer(initial_num_pizzas, total_num_pizzas, q):
    """Cooks Pizzas to be consumed and waits for the consumer to finish eating."""
    print("Producer: I am cooking %s Pizzas and putting them on the Queue!"%(total_num_pizzas-initial_num_pizzas))
    for i in range(q.qsize(), total_num_pizzas):
        print("Producer: Behold, for I have cooked Pizza no. %s"%i)
        q.put(Pizza(i))
    q.put(sentinel)

def consumer(q):
    """Consumes some Pizza. In this case, all it does is set the number of slices to 0."""
    while True:
        pizza = q.get()
        pizza.num_slices = 0
        if pizza == sentinel:
            break
        print("Comsumer: Pizza no. %s was found! It has %s slices, yum!"%(pizza.pizza_num, pizza.num_slices))

if __name__ == '__main__':
    q = Queue()
    total_num_pizzas = 10
    initial_num_pizzas = 4
    ## Let's add some Pizzas beforehand:
    for i in range(0, initial_num_pizzas):
        q.put(Pizza(i))
    print("Main: I have precooked %s Pizzas."%q.qsize())

    producer_proc = Process(target=producer, args=(initial_num_pizzas, total_num_pizzas, q))
    consumer_proc = Process(target=consumer, args=(q,))
    producer_proc.start()
    consumer_proc.start()

    q.close()  ## Shop is closed, no more Pizzas will be added to Queue!
    q.join_thread()

    producer_proc.join()
    consumer_proc.join()

Below is an example output. 下面是一个示例输出。 If you run it, the Producer and Consumer print statements may be interleaved differently, because of non-deterministic execution of parallel processes. 如果运行它,Producer和Consumer打印语句可能会以不同方式交错,因为并行进程的执行不确定。

Main: I have precooked 4 Pizzas.
Producer: I am cooking 6 Pizzas and putting them on the Queue!
Producer: Behold, for I have cooked Pizza no. 4
Producer: Behold, for I have cooked Pizza no. 5
Producer: Behold, for I have cooked Pizza no. 6
Producer: Behold, for I have cooked Pizza no. 7
Comsumer: Pizza no. 0 was found! It has 8 slices, yum!
Comsumer: Pizza no. 1 was found! It has 8 slices, yum!
Producer: Behold, for I have cooked Pizza no. 8
Comsumer: Pizza no. 2 was found! It has 8 slices, yum!
Producer: Behold, for I have cooked Pizza no. 9
Comsumer: Pizza no. 3 was found! It has 8 slices, yum!
Comsumer: Pizza no. 4 was found! It has 8 slices, yum!
Comsumer: Pizza no. 5 was found! It has 8 slices, yum!
Comsumer: Pizza no. 6 was found! It has 8 slices, yum!
Comsumer: Pizza no. 7 was found! It has 8 slices, yum!
Comsumer: Pizza no. 8 was found! It has 8 slices, yum!
Comsumer: Pizza no. 9 was found! It has 8 slices, yum!

Note that you should use Sentinels to mark the end of your Queue . 请注意,您应该使用Sentinels标记队列的结尾 I've used "NO PIZZA" here, but they can be anything at all. 我在这里使用过“NO PIZZA”,但它们可以是任何东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM