【问题标题】:Google Cloud Function crashes with TypeError: 'Request' object is not subscriptableGoogle Cloud Function 因 TypeError 崩溃:“请求”对象不可下标
【发布时间】:2020-07-28 09:02:02
【问题描述】:

我已经部署了一个谷歌云函数,并通过一个带有 URL 查询字符串参数的 http GET 请求访问它。

但是,它失败并显示“错误:无法处理请求”。

当我从 Colab 笔记本运行该功能时,该功能运行良好。

我在下面分享函数代码(main.py)、requirements.txt和错误日志:

main.py:

from goose3 import Goose
import validators
import json
from transformers import pipeline

def respond(err, res=None):
    print(err)
    print(res)
    return {
        'statusCode': '400' if err else '200',
        'body': err['message'] if err else json.dumps(res),
        'headers': {
            'Content-Type': 'application/json',
        },
    }

def extract_html(url):

    extractor = Goose({'browser_user_agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2)','strict': False})
    article = extractor.extract(url=url)
    text = article.cleaned_text
    info = article.infos
    print("Extracted {} words.".format( str(len(text.split(' '))) ))

    return info, text

def t5(event):

    qs = event['queryStringParameters']
    if qs and 'url' in qs:
        url = qs['url']
        print(url)

        try:
            validators.url(url)
            info, text = extract_html(url)
            nlp_t5 = pipeline('summarization', model="t5-small", tokenizer="t5-small")
            summary = nlp_t5(text)
            data = {'url': url,
                    'info': info,
                    'meta_description': summary
                    }
            return respond(None, data)

        except ValidationFailure as e:
            err = {'message': 'Not a valid URL.'}
            return respond(err)

        except Exception as e:
            err = {'message': str(e)}
            return respond(err)

    else:
        return respond(ValueError('Missing parameter `url`.'))

requirements.txt:

https://download.pytorch.org/whl/cpu/torch-1.0.1.post2-cp37-cp37m-linux_x86_64.whl
transformers==2.7.0
validators==0.14.3
goose3==3.1.6

错误日志:

{
 insertId: "xxxx-cea02c1b8e9a"  
 labels: {
  execution_id: "oq7e8d7dryic"   
 }
 logName: "xxxxxxx/cloudfunctions.googleapis.com%2Fcloud-functions"  
 receiveTimestamp: "2020-04-15T11:21:52.415338305Z"  
 resource: {
  labels: {
   function_name: "t5"    
   project_id: "xxxx"    
   region: "us-central1"    
  }
  type: "cloud_function"   
 }
 severity: "ERROR"  
 textPayload: "Traceback (most recent call last):
  File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker.py", line 346, in run_http_function
    result = _function_handler.invoke_user_function(flask.request)
  File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker.py", line 217, in invoke_user_function
    return call_user_function(request_or_event)
  File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker.py", line 210, in call_user_function
    return self._user_function(request_or_event)
  File "/user_code/main.py", line 30, in t5
    qs = event['queryStringParameters']
  File "/env/local/lib/python3.7/site-packages/werkzeug/local.py", line 377, in <lambda>
    __getitem__ = lambda x, i: x._get_current_object()[i]
TypeError: 'Request' object is not subscriptable
"  
 timestamp: "2020-04-15T11:21:51.928Z"  
 trace: "xxxxxxx/traces/ac5c24180c1fce71fdcf32e39d88d1ff"  
}

示例触发事件:

{
  "httpMethod": "GET",
  "queryStringParameters": {
    "url": "https://www.webmd.com/rx/physicians/"
  }
}

我已经四处寻找解决方案,但没有找到任何解决方案。

非常感谢。

【问题讨论】:

  • 只是好奇:是什么让您认为可以在这里使用event['queryStringParameters']?该示例是否在某处的某些 GCP 文档中使用过?
  • 到目前为止,我一直在使用 AWS lambda 函数,并做出了错误的假设(可能是初学者的错误,对此深表歉意!)相同的请求对象也可以在 Google Cloud Functions 上运行。没有意识到这里的请求对象是一个Flask对象。感谢您指出。

标签: python google-cloud-platform google-cloud-functions


【解决方案1】:

你在做:

def t5(event):
    qs = event['queryStringParameters']
    if qs and 'url' in qs:
        url = qs['url']
        ...

但是这里传递给函数的对象是Flask request object,所以你需要这样做:

def t5(event):
    url = event.args.get("url")
    if url:
        ...

我建议重命名参数,以免与 background function 混淆:

def t5(request):
    url = request.args.get("url")
    if url:
        ...

您还需要更新您的 respond 方法以返回字符串、元组或 Response 实例。比如:

def respond(err, res=None):
    print(err)
    print(res)

    if err:
        return err['message'], 400, {'Content-Type': 'application/json'}
    else:
        return json.dumps(res), 200, {'Content-Type': 'application/json'}

【讨论】:

  • 谢谢你的回答,达斯汀。我实现了上述内容,现在出现以下错误:TypeError: 'dict' object is not callable The view function did not return a valid response. The return type must be a string, tuple, Response instance, or WSGI callable, but it was a dict.我的响应对象是否也出错了?抱歉,我是 Google Cloud Functions 的初学者。到现在为止一直在使用 AWS lambda 函数,我只是在切换。
猜你喜欢
  • 2021-11-16
  • 1970-01-01
  • 2021-11-04
  • 2018-05-02
  • 1970-01-01
  • 1970-01-01
  • 2016-07-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多