我确信之前已经提出了许多类似的问题,但在阅读了很多这些问题后,我仍然不太确定应该做些什么。所以,我有一个Python脚本来控制一些外部仪器(摄像头和功率计)。我通过使用ctypes调用.dll文件中的C函数为两种乐器编写了类。现在它看起来像这样:
for i in range(10):
power_reading = newport.get_reading(N=100,interval=1) # take power meter reading
img = camera.capture(N=10)
value = image_processing(img) # analyze the img (ndarray) to get some values
results.append([power_reading,value]) # add both results to a list
我想同时开始执行前两行。 newport.get_reading
和camera.capture
都需要大约100ms-1s运行(如果我选择正确的参数,它们将运行相同的时间)。我不需要它们在同一时间完全启动,但理想情况下延迟应小于总运行时间的约10-20%(因此每次运行时需要少于0.2秒的延迟运行) 。根据我的阅读,我可以使用multiprocessing
模块。所以我根据这个post尝试这样的事情:
def p_get_reading(newport,N,interval,return_dict):
reading = newport.get_reading(N,interval,return_dict)
return_dict['power_meter'] = reading
def p_capture(camera,N,return_dict):
img = camera.capture(N)
return_dict['image'] = img
for i in range(10):
manager = multiprocessing.Manager()
return_dict = manager.dict()
p = multiprocessing.Process(target=p_capture, args=(camera,10))
p.start()
p2 = multiprocessing.Process(target=p_get_reading, args=(newport,100,1))
p2.start()
p.join()
p2.join()
print(return_dict)
我有一些问题/疑问:
我需要从两个函数调用中获取返回值。使用我当前的方法,return_dict
仅显示capture_img
的条目,但不显示功率计读数,为什么会这样?它还读到我可以使用Queue
,目前最好的方法是什么?
我如何知道这两个功能是否确实同时开始运行?我正在考虑使用time
模块来记录两个函数的开始和结束时间,可能使用一些包装函数来进行时间记录,但使用multiprocessing
是否会构成任何限制?< / p>
我通常在IDE(spyder)上运行我的代码,根据我的阅读,我需要在命令提示符下运行以查看输出(我在函数内部有一些打印语句用于调试目的)。我是否仍然可以在IDE中运行以同时运行这两个功能?
答案 0 :(得分:3)
使用Lock
可能有助于同步:
import multiprocessing
def p_get_reading(newport, N, interval, lock, return_dict):
lock.acquire()
lock.release()
reading = newport.get_reading(N, interval)
return_dict['power_meter'] = reading
def p_capture(camera, N, lock, return_dict):
lock.acquire()
lock.release()
img = camera.capture(N)
return_dict['image'] = img
if __name__ == "__main__":
for i in range(10):
manager = multiprocessing.Manager()
return_dict = manager.dict()
lock = multiprocessing.Lock()
lock.acquire()
p = multiprocessing.Process(target=p_capture, args=(camera,10,lock,return_dict))
p.start()
p2 = multiprocessing.Process(target=p_get_reading, args=(newport,100,1,lock,return_dict))
p2.start()
lock.release()
p.join()
p2.join()
print(return_dict)
现在可以按任何顺序创建两个Process
对象,因为主例程已经获得了锁定。一旦发布,这两个进程将在它们之间争夺获取和释放锁定,并且同时准备好 。
此外,请注意使用start()
,因为这有助于if __name__ == "__main__"
制作新流程。
我必须说这似乎是滥用multiprocessing
答案 1 :(得分:1)
回答你的第一个问题,如果你是以正常方式做的话,那就不是,但是如果你想要,那就是。否,因为目标函数无法使用return
与产卵线程进行通信。一种方法是使用队列和包装函数如下:
from threading import Thread
from Queue import Queue
def p_get_reading(newport,N,interval,return_dict):
reading = newport.get_reading(N,interval,return_dict)
return_dict.update({'power_meter': reading})
return return_dict
def p_capture(camera,N,return_dict):
img = camera.capture(N)
return_dict.update({'image': img})
return return_dict
def wrapper1(func, arg1, arg2, queue):
queue.put(func(arg1, arg2))
def wrapper2(func, arg1, arg2, arg3, queue):
queue.put(func(arg1, arg2, arg3))
q = Queue()
Thread(target=wrapper1, args=(p_capture, camera, 10 , q)).start()
Thread(target=wrapper2, args=(p_get_reading, newport, 100, 1, q)).start()
现在q
保留已更新并从dict
和p_capture()
返回p_get_reading()
。