我想同时控制和运行两个实验室设备(至少同时启动它们),所以我使用多处理模块。
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;方法)。我不确定哪个部分导致问题。我应该如何修改代码才能使其正常工作?
答案 0 :(得分:1)
在这种情况下,在将参数传递给将作为新(子)进程执行的target
方法时执行pickle。
确切地说,我不确定是否可以使用DCx_camera
和Newport1936R
的酸洗实例。取决于如何定义这些类,但看看错误消息,我想你不能。这就是为什么你可以尝试根本不传递这些引用。通过这个例子,你似乎不需要这样做。
这是我期望的工作:
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_camera
和Newport1936R
实例的全局变量,然后在两种目标方法中使用它们。