Flask API 路由未捕获异常

Flask API Routes not catching exceptions

可能对 Flask 如何处理错误有点困惑。致力于向数据库后端添加错误处理。我基本上有一个工作脚本、一个路由器和一个错误处理脚本。

错误处理非常简单。我有一个包含以下 类 的单独模块。它们继承自异常,因此没有添加太多

class EmptyQueryError(Exception):
    pass

class BadURLError(Exception):
    pass

我的主要路由方法如下,调用了一个处理post process/etc.

的方法
def queryJobData(projectId, jobId): 
    try:
        dbv.jobData(projectId, jobId)
    except EmptyQueryError as e:
        abort(400, "An unexpected Exception Occurred: {}".format(e))
    except Exception as e:
        abort(400, "An unexpected Exception Occurred: {}".format(e))

最后,主要的驱动函数包含在about的dbv对象中。这个流程正常工作,至于当我传入有价值的项目和工作 ID 时,查询成功并且它 returns 是我想要的文档。但是,当我故意插入错误以引发异常时,这就是问题发生的地方。这是处理函数:

def jobData(self, projectId, jobId):
    try:
        print("[Querying the job data]")
        if (request.method == "GET"):
            qData = [x for x in self.collection.find({"projectId": projectId, "jobId": jobId})]
            # input(qData)
            if (len(qData) == 0):
                raise EmptyQueryError("EmptyQueryError: The url you attempted to query did not return any data")
            pp.data = qData
            unrolled_data = pp.unrollData()
            df = pd.DataFrame(unrolled_data)

            pps = PostProcessSummary(df)
            table_test = pps.pivot_summary()
            return dumps(table_test)


    except Exception as e:
        print(e)
    finally:
        pass

我故意没有导入“请求”模块,所以它引发了错误。我可以看到它被“jobData”捕获:

但是,它从未进入调用句柄“jobData”的“queryJobData”中的异常块之一。

至少可以说这让我陷入了一个循环。我构建的几乎所有其他软件都会相应地处理这个异常。 (即它遵循这样一种模式,即如果在其他地方引发了一个异常,则应该由调用生成异常的子进程的父进程来处理)。第一次使用 Flask,所以我想我遗漏了一些我在文档中找不到的明显内容。

编辑: jobData() 中的异常被捕获,并返回到 queryJobData() 中,就好像什么都没发生一样。例如,在此块中,它直接转到 return 而不是处理引发的异常

try:
    dbv_ret = dbv.jobData(projectId, jobId)
    return dbv_ret
except TypeError:
    abort(400, "TypeError Occurred")
except EmptyQueryError:
    print("[ARE WE HERE?!]")
    abort(404, "Empty Query")
except BadURLError:
    abort(404, "Bad URL")
except Exception as e:
    abort(404, "An unexptec exception has occurred: {}".format(e))

您在函数中捕获了所有异常,因此 在 try/except 块中发生的任何事情都将在您的 except 块中捕获 ,然后您的 finally 块将被执行。

如果要将 EmptyQueryError 和 BadURLError 异常传递给调用函数,请在 try/except 块之外引发它。或者,如果你愿意,re-raise 它在你的 except 块中

class EmptyQueryError(Exception):
    pass

class BadURLError(Exception):
    pass


def jobData():
    try:
        print("[Querying the job data]")
        # this will be caught by the except block
        raise EmptyQueryError("EmptyQueryError: The url you attempted to query did not return any data")


    except Exception as e:
        # catching all exceptions. Including the ones you are raising.
        # if you don't re-raise the exception here, no error will be passed
        print("Wow, exception")
        print(e)
    finally:
        print("I'm in finally block ;)")
        # not returning anything
        pass


if __name__ == "__main__":
    try:
        returned_value = jobData()
        # will print None
        print(returned_value)
    except EmptyQueryError as query_err:
        # will never be caught
        print("Got a EmptyQueryError")
    except BadURLError as url_err:
        # will never be caught
        print("Got a BadURLError")

打印顺序为:

[Querying the job data]
Wow, exception
EmptyQueryError: The url you attempted to query did not return any data
I'm in finally block ;)
None

您可以这样做:

def jobData(data):
    if len(data) == 0:
        raise EmptyQueryError("EmptyQueryError: The url you attempted to query did not return any data")

    try:
        # do your thing here
        pass
    except Exception as e:
        print(e)
    finally:
        print("I'm in finally block ;)")
        # not returning anything
        pass

现在 EmptyQueryError 将被调用函数捕获。