Python 我的进程完成了它的“run”功能,但它没有';别死
我正在子类化Python 我的进程完成了它的“run”功能,但它没有';别死,python,python-multiprocessing,Python,Python Multiprocessing,我正在子类化多处理。Process以创建一个类,该类将异步地从相机抓取图像,并将其推送到一些队列中以显示和保存到磁盘 我遇到的问题是,当我使用属于进程子体对象的多处理.Event对象发出停止命令时,进程成功地完成了run函数的最后一行,但之后它不会死。该进程只是继续存在,并继续从is\u alive函数返回true。我不明白这怎么可能。什么会导致进程完成其运行功能而不死亡 令人发狂的是,当我将这个对象与我正在使用它的更大的上下文(其中包括几个同时运行的其他流程子类)分离时,我无法重现这个问题,这
多处理。Process
以创建一个类,该类将异步地从相机抓取图像,并将其推送到一些队列中以显示和保存到磁盘
我遇到的问题是,当我使用属于进程子体对象的多处理.Event
对象发出停止命令时,进程成功地完成了run
函数的最后一行,但之后它不会死。该进程只是继续存在,并继续从is\u alive
函数返回true。我不明白这怎么可能。什么会导致进程完成其运行
功能而不死亡
令人发狂的是,当我将这个对象与我正在使用它的更大的上下文(其中包括几个同时运行的其他流程子类)分离时,我无法重现这个问题,这往往会让我认为它与代码的其余部分有关,但我不明白这是怎么回事——如果它执行了run
函数的最后一行,那么不管发生了什么,它不应该死掉吗?我一定是误解了进程对象的工作原理
下面是代码。当我运行它时,我看到消息“Video acquires process STOPPED”(视频采集进程已停止)打印出来,但进程并没有停止
class VideoAcquirer(mp.Process):
def __init__(self, camSerial, imageQueue, monitorImageQueue, acquireSettings={}, monitorFrameRate=15):
mp.Process.__init__(self, daemon=True)
self.camSerial = camSerial
self.acquireSettings = acquireSettings
self.imageQueue = imageQueue
self.monitorImageQueue = monitorImageQueue
self.videoFrequencyEntry.get()Rate = monitorFrameRate
self.stop = mp.Event()
def stopProcess(self):
print('Stopping video acquire process')
self.stop.set()
def run(self):
system = PySpin.System.GetInstance()
camList = system.GetCameras()
cam = camList.GetBySerial(self.camSerial)
cam.Init()
nodemap = cam.GetNodeMap()
setCameraAttributes(nodemap, self.acquireSettings)
cam.BeginAcquisition()
monitorFramePeriod = 1.0/self.monitorFrameRate
print("Video monitor frame period:", monitorFramePeriod)
lastTime = time.time()
k = 0
im = imp = imageResult = None
print("Image acquisition begins now!")
while not self.stop.is_set():
try:
# Retrieve next received image
print(1)
imageResult = cam.GetNextImage(100) # Timeout of 100 ms to allow for stopping process
print(2)
# Ensure image completion
if imageResult.IsIncomplete():
print('Image incomplete with image status %d...' % imageResult.GetImageStatus())
else:
# Print image information; height and width recorded in pixels
width = imageResult.GetWidth()
height = imageResult.GetHeight()
k = k + 1
print('Grabbed Image %d, width = %d, height = %d' % (k, width, height))
im = imageResult.Convert(PySpin.PixelFormat_Mono8, PySpin.HQ_LINEAR)
imp = PickleableImage(im.GetWidth(), im.GetHeight(), 0, 0, im.GetPixelFormat(), im.GetData())
self.imageQueue.put(imp)
# Put the occasional image in the monitor queue for the UI
thisTime = time.time()
if (thisTime - lastTime) >= monitorFramePeriod:
# print("Sent frame for monitoring")
self.monitorImageQueue.put((self.camSerial, imp))
lastTime = thisTime
imageResult.Release()
print(3)
except PySpin.SpinnakerException as ex:
pass # Hopefully this is just because there was no image in camera buffer
# print('Error: %s' % ex)
# traceback.print_exc()
# return False
# Send stop signal to write process
print(4)
self.imageQueue.put(None)
camList.Clear()
cam.EndAcquisition()
cam.DeInit()
print(5)
del cam
system.ReleaseInstance()
del nodemap
del imageResult
del im
del imp
del camList
del system
print("Video acquire process STOPPED")
我从tkinter GUI线程开始这个过程,大致如下:
import multiprocessing as mp
camSerial = '2318921'
queue = mp.Queue()
videoMonitorQueue = mp.Queue()
acquireSettings = [('AcquisitionMode', 'Continuous'), ('TriggerMode', 'Off'), ('TriggerSource', 'Line0'), ('TriggerMode', 'On')]
v = VideoAcquirer(camSerial, queue, videoMonitorQueue, acquireSettings=acquireSettings, monitorFrameRate=15)
下面是我如何停止进程的大致方式,也是从tkinter GUI线程:
v.stopProcess()
感谢您的帮助。也许向我们展示如何在您的实际环境中使用它会有所帮助。在流程中附加一个调试器,以了解它应该停止时实际在做什么,怎么样?您是否必须在流程正确完成之前加入该流程?@Sraw我同意这会很有用,但其余的代码相当大。通常我会发布一个最小的工作(或非工作)示例,但在这种情况下,当我试图隔离这个类时,我无法重现错误@DanielJunglas听起来很有用-我从来没有这样做过,但我会研究一下,谢谢。让我们看看你如何称呼这个过程?