Flask API服务对象检测因并发请求而损坏

2024-04-20 09:52:43 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在开发一个由Flask(Github repo)提供的简单机器学习API。到目前为止,我的做法是:

  • 当应用程序第一次启动时,我有两个全局变量,face_objod_obj,它们加载人脸识别(dlib)和对象检测(YoloV3)模型。我的目标是在应用程序开始时只做一次,因为模型加载很昂贵
  • 然后,我通过app.run(...)运行应用程序并等待请求。我正在运行Flask1.0.2,据我所知,它默认为线程模式,这就是我希望能够同时为请求提供服务的方式
  • 然后我等待请求,并根据传递的查询参数(type=facetype=object),调用任一对象的.detect()函数并返回检测到的JSON提要

我面临的问题是,当我的应用程序接收到多个并发请求时,比如说两个对象检测请求一起,对象检测会完全出错并返回不正确的结果。按顺序调用时,一切正常

这是我的主要代码(api.py):

一开始:

# my two globals 
face_obj = FaceRecog.Face()
od_obj = ObjectDetect.Object()

然后在我的检测类中,基于API参数,我调用人脸或对象检测:

class Detect(Resource):
    @jwt_required
    def post(self):
        args = parse_args()

        if args['type'] == 'face':
            m = face_obj
            g.log.debug ('Face Recognition requested')

        elif args['type'] in [None, 'object']:
            m = od_obj
            g.log.debug ('Object Recognition requested')

        else:
            abort(400, msg='Invalid Model:{}'.format(args['type']))
        fip,ext = get_file(args)
        fi = fip+ext
        image = cv2.imread(fi)
        detections = m.detect(image)
        return detections

{a3}是使用OpenCV或dlib的python包装器的标准python检测包装器

我不明白为什么检测会被破坏。我的理解是,当我启动线程时,线程会自动创建对象的副本,因此不应该有任何损坏的原因

我已经链接到上面的完整项目,如果它有帮助的话

我在别处读到过(Are global variables thread safe in flask? How do I share data between requests?)全局变量在Flask中不是线程安全的,那么我应该将face_objod_obj实例转换为会话变量吗?基于对该线程的读取,任务似乎是在线程之间共享/影响数据。在我的例子中,我不希望线程更改数据。我只想将one-time-load模型传递给多个检测请求


Tags: 对象模型apiobj应用程序flask参数object