Celery定时任务在几次节拍后停止失败(opencv)

0 投票
1 回答
618 浏览
提问于 2025-04-17 23:40

我有一个celery任务,每60秒运行一次,目的是抓取一个网络摄像头,拍一张静态图片,然后把它写入文件,以便服务器可以在网页上展示。这个拍照的过程是通过Python中的cv2库,也就是opencv来实现的。

它的代码大致是这样的:

    @app.task                               # a task to get and save a webcam image
    def getWebCamImage()                    
    logger.debug("capturing image attempt")
    c = cv2.VideoCapture(0)                 #returns a videocapture object
    flag, frame = c.read()                  #grabs and decodes the next frame
    cv2.imwrite('file/loc/img.jpg, frame)   #writes the frame to a file
    logger.debug('saved image...hopefully') 
    c.release()                             #releases the videocapture object
    return 0

一开始运行得很顺利,但过了几分钟后,就会出现一些正常的错误,提示无法获取摄像头的属性,然后就停止了。而且它再也不会重新启动了!

    ...DEBUG/BEAT] celerytest.getwebcamimage[process]:capturing image attempt
    VIDOC_QUERYMENU:Invalid argument
    VIDOC_QUERYMENU:Invalid argument
    VIDOC_QUERYMENU:Invalid argument

当它正常工作时就是这样的情况,只是它会一直运行下去。你觉得是什么原因导致它停止的呢?我是在一个树莓派上运行这个程序,给ARM核心分配了240MB内存,给图形分配了16MB。

我尝试过的一些解决方法:

    $sudo sysctl vm.overvommit_memory=1

所以它没有抛出内存分配错误。 $sudo rmmod ucvideo $sudo modprobe ucvideo nodrop=1 timeout=5000 quirks=0x80 这样驱动程序对摄像头就更耐心了。我尝试过几种摄像头,所以这可能不是问题所在。

请帮忙提供任何建议或测试方法。这是个棘手的问题,因为它是在树莓派上运行,并且是树莓派和celery的结合。我打算试着用guvcview运行一个脚本,但我觉得用Python和opencv的方式更简单,因为安装起来更方便,而且无论如何我都想知道为什么这个方法不行!

最新消息:

通过DMESG命令发现,一个celery进程因为内存不足而被杀掉了。有没有办法解决这个问题?在任务中创建的对象是如何被销毁的?

1 个回答

0

这其实和Celery没有关系,而是和cv有关。

每次释放CV2.videocapture对象时,如果没有把它删除,内存就会一直被占用。在内存非常少的树莓派上,这很快就会占满所有内存,导致程序被杀掉。我是通过Linux中的top命令来查看内存使用情况的。

在更大的电脑上也会出现这种情况,但在树莓派上问题更严重。

撰写回答