N次后终止cv2读取过程



我绝望了。

我的代码在视频中读取nframe,有时代码会无故停止,而且不会出错。所以我决定以某种方式提出一个错误。问题是,代码确实引发了一个错误,但由于某种原因,它忽略了它,并且正常工作。

*我提供了一个代码块,完全相同的方法也适用于该代码块。

处理程序:

def handler(signum,frame):
print("error") ## This is printed
raise Exception('time out') ## I guess this is getting raised

我想包装的代码部分:

for i in range(0,int(frame_count), nframe): # basicly loads every nframe from the video
try:
frame = video.set(1,i)
signal.signal(signal.SIGALRM), handler)
signal.alarm(1) # At this point, the 'handler' did raise the error, but it did not kill this 'try' block.
_n,frame = video.read() # This line sometimes gets for infinit amount of time, and i want to wrap it
except Exception as e:
print('test') # Code does not get here, yet the 'handler' does raise an exception
raise e
# Here i need to return False, or rise an error, but the code just does not get here.

一个完全相同的方法将起作用的例子:

import signal
import time
def handler(signum, frame):
raise Exception('time out')
def function():
try:
signal.signal(signal.SIGALRM,handler)
signal.alarm(5) # 5 seconds till raise
time.sleep(10) # does not get here, an Exception is raised after 5 seconds
except Exception as e:
raise e # This will indeed work

我的猜测是read()调用在C代码中的某个地方被阻塞了。信号处理程序运行,将异常放入Python解释器的某个位置,但在Python解释器重新获得控制之前不会处理该异常。这是signal模块中记录的限制:

纯用C实现的长时间运行的计算(例如对大量文本进行正则表达式匹配(可能会在任意时间内不间断地运行,而与接收到的任何信号无关。当计算完成时,将调用Python信号处理程序。

一种可能的解决方法是使用multiprocessing模块读取单独进程上的帧,并使用multiprocessing.Queue将它们返回到主进程(您可以从中超时get(。然而,在进程之间发送帧会有额外的开销。

另一种方法可能是尽量避免问题的根源。OpenCV有不同的视频后端(V4L、GStreamer、ffmpeg等(;其中一个可能在另一个不工作的地方工作。使用VideoCapture构造函数的第二个参数,可以指示要使用哪个后端的首选项:

cv.VideoCapture(..., cv.CAP_FFMPEG)

有关后端的完整列表,请参阅文档。根据您的平台和OpenCV构建,并非所有这些都可用。

最新更新