【问题标题】:try except not catching on function?尝试除了不赶上功能?
【发布时间】:2019-04-12 02:08:37
【问题描述】:

我在预处理一些数据时遇到了这个错误:

 9:46:56.323 PM default_model Function execution took 6008 ms, finished with status: 'crash'
 9:46:56.322 PM default_model Traceback (most recent call last):
  File "/user_code/main.py", line 31, in default_model
    train, endog, exog, _, _, rawDf = preprocess(ledger, apps)
  File "/user_code/Wrangling.py", line 73, in preprocess
    raise InsufficientTimespanError(args=(appDf, locDf))

这里发生了:

async def default_model(request):
    request_json = request.get_json()
    if not request_json:
        return '{"error": "empty body." }'
    if 'transaction_id' in request_json:
        transaction_id = request_json['transaction_id']

        apps = []  # array of apps whose predictions we want, or uempty for all
        if 'apps' in request_json:
            apps = request_json['apps']

        modelUrl = None
        if 'files' in request_json:
            try:
                files = request_json['files']
                modelUrl = getModelFromFiles(files)
            except:
                return package(transaction_id, error="no model to execute")
        else:
            return package(transaction_id, error="no model to execute")

        if 'ledger' in request_json:
            ledger = request_json['ledger']

            try:
                train, endog, exog, _, _, rawDf = preprocess(ledger, apps)
            # ...
            except InsufficientTimespanError as err:
                return package(transaction_id, error=err.message, appDf=err.args[0], locDf=err.args[1])

并且预处理正确地抛出了我的自定义错误:

def preprocess(ledger, apps=[]):
    """
    convert ledger from the server, which comes in as an array of csv entries.
    normalize/resample timeseries, returning dataframes
    """
    appDf, locDf = splitLedger(ledger)

    if len(appDf) < 3 or len(locDf) < 3:
        raise InsufficientDataError(args=(appDf, locDf))

    endog = appDf['app_id'].unique().tolist()
    exog = locDf['location_id'].unique().tolist()

    rawDf = normalize(appDf, locDf)
    trainDf = cutoff(rawDf.copy(), apps)
    rawDf = cutoff(rawDf.copy(), apps, trim=False)

    # TODO - uncomment when on realish data
    if len(trainDf) < 2 * WEEKS:
        raise InsufficientTimespanError(args=(appDf, locDf))

问题是,它位于 try``except 块中,正是因为我想捕获错误并返回带有错误的有效负载,而不是因为 500 错误而崩溃。但无论如何,它在我的自定义错误中崩溃,在 try 块中。就在那条线上,打电话给preprocess

这一定是我未能遵守正确的 python 代码。但我不确定我做错了什么。环境是python 3.7

这是在 Wrangling.py 中定义错误的地方:

class WranglingError(Exception):
    """Base class for other exceptions"""
    pass


class InsufficientDataError(WranglingError):
    """insufficient data to make a prediction"""

    def __init__(self, message='insufficient data to make a prediction', args=None):
        super().__init__(message)
        self.message = message
        self.args = args


class InsufficientTimespanError(WranglingError):
    """insufficient timespan to make a prediction"""

    def __init__(self, message='insufficient timespan to make a prediction', args=None):
        super().__init__(message)
        self.message = message
        self.args = args

这是 main.py 声明(导入)它的方式:

from Wrangling import preprocess, InsufficientDataError, InsufficientTimespanError, DataNotNormal, InappropriateValueToPredict

【问题讨论】:

  • 向我们展示InsufficientTimespanErrormain.pyWrangling.py 中的定义。
  • 现在添加
  • 我被难住了......
  • 如果在preprocess() 的顶部添加另一个raise InsufficientTimespanError(...) 语句会发生什么?它能正确捕捉到那个吗?
  • @JohnGordon 好主意,感谢您与我一起思考这个问题。我将raise InsufficientTimespanError(args=(pd.DataFrame(), pd.DataFrame())) 放在方法的顶部 - 它仍然以相同的方式崩溃:(

标签: python google-cloud-functions


【解决方案1】:

您的preprocess 函数声明为async。这意味着其中的代码实际上并没有在您调用preprocess 的地方运行,而是在最终被awaited 或传递给主循环时(如asyncio.run)。因为它运行的地方已经不在default_model的try块中,所以没有捕获到异常。

您可以通过以下几种方式解决此问题:

  • 使preprocess 不是异步的
  • 使default_model 也异步,并在preprocess 上设置await

【讨论】:

  • 我很抱歉。我已经从default_model 方法中删除了“异步”,而不是从preprocess 中删除——在发布此内容时,我正在试验它并复制并粘贴了该函数,同时它添加了异步。我仍然收到异步 default_model 和同步 preprocess 的错误
【解决方案2】:

错误中的行号是否与代码中的行号匹配?如果不是,您是否有可能在添加 try...except 之前从代码版本中看到错误?

【讨论】:

  • 是的,他们确实这样做了——在这一点上,我很确定这在某种程度上是谷歌云函数环境对 python 3.7 的影响。我注意到的另一件事是,我无法通过将在 with 块中导入,我还必须将所有调用的使用都放在自己的 with 块中。这与许多仅通过包装导入以不同方式工作的示例相反。
猜你喜欢
  • 1970-01-01
  • 2019-01-21
  • 1970-01-01
  • 2019-09-25
  • 2011-07-04
  • 1970-01-01
  • 2018-08-24
  • 1970-01-01
  • 2022-11-01
相关资源
最近更新 更多