使用多处理时的酸洗错误

时间:2018-02-15 13:42:53

标签: python-3.x class multiprocessing pickle python-multiprocessing

我想同时控制和运行两个实验室设备(至少同时启动它们),所以我使用多处理模块。

from myLabModule import Newport1936R
from myLabModule import DCx_camera
from multiprocessing import Process, Queue

def multiprocess_camera(camera, shots_per_img, queue, delay):
    time.sleep(delay)
    img, camera_time = camera.capture(shots_per_img, np.float64, True) #img is a 2x2 ndarray
    results = [camera_time[0], camera_time[1], img, 'img']
    queue.put(results)

def multiprocess_power(newport, interval, N, queue, delay):
    time.sleep(delay)
    power_reading, newport_time = newport.get_power(interval, N, True)
    results = [newport_time[0], newport_time[1], power_reading, 'power']
    queue.put(results)

if __name__ == "__main__":
    thorcam = DCx_camera()
    newport = Newport1936R()
    queue = Queue()
    p1 = Process(target=multiprocess_camera, args=(thorcam,10,queue,0))
    p2 = Process(target=multiprocess_power, args=(newport,1,10,queue,0))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    results = []
    results.append(queue.get())
    results.append(queue.get())

当我运行代码时,出现以下错误:AttributeError: Can't pickle local object 'CDLL.__init__.<locals>._FuncPtr'。我读了这个post,似乎它与变量的范围有关(我将另一个模块中定义的两个classess传递给函数,而函数基本上运行类&#39;方法)。我不确定哪个部分导致问题。我应该如何修改代码才能使其正常工作?

1 个答案:

答案 0 :(得分:1)

在这种情况下,在将参数传递给将作为新(子)进程执行的target方法时执行pickle。

确切地说,我不确定是否可以使用DCx_cameraNewport1936R的酸洗实例。取决于如何定义这些类,但看看错误消息,我想你不能。这就是为什么你可以尝试根本不传递这些引用。通过这个例子,你似乎不需要这样做。

这是我期望的工作:

from myLabModule import Newport1936R
from myLabModule import DCx_camera
from multiprocessing import Process, Queue

def multiprocess_camera(shots_per_img, queue, delay):
    camera = DCx_camera()
    time.sleep(delay)
    img, camera_time = camera.capture(shots_per_img, np.float64, True) #img is a 2x2 ndarray
    results = [camera_time[0], camera_time[1], img, 'img']
    queue.put(results)

def multiprocess_power(interval, N, queue, delay):
    newport = Newport1936R()
    time.sleep(delay)
    power_reading, newport_time = newport.get_power(interval, N, True)
    results = [newport_time[0], newport_time[1], power_reading, 'power']
    queue.put(results)

if __name__ == "__main__":
    queue = Queue()
    p1 = Process(target=multiprocess_camera, args=(10,queue,0))
    p2 = Process(target=multiprocess_power, args=(1,10,queue,0))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    results = []
    results.append(queue.get())
    results.append(queue.get())

这是否可以获得理想的效果?

根据此link,还有另一种选择。

  

最好继承而不是pickle / unpickle

     

但是,人们通常应该避免   使用管道或队列将共享对象发送到其他进程。   相反,你应该安排程序,以便需要一个过程   访问在其他地方创建的共享资源可以从中继承它   祖先过程。

这就是为什么我认为你甚至可以拥有引用DCx_cameraNewport1936R实例的全局变量,然后在两种目标方法中使用它们。