Сбой функции Google Cloud при ошибке TypeError: объект «Запрос» не является подписным - PullRequest
1 голос
/ 15 апреля 2020

Я развернул облачную функцию Google и обращаюсь к ней по запросу HTTP GET с параметрами строки запроса URL.

Однако происходит сбой с сообщением «Ошибка: не удалось обработать запрос».

Функция отлично работает, хотя я запускаю ее из записной книжки Colab.

Я делюсь кодом функции (main.py), needs.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`.'))

needs.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/"
  }
}

Я искал решения для этого, но не смог найти ни одного.

Заранее большое спасибо.

1 Ответ

1 голос
/ 15 апреля 2020

Вы делаете:

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

, но объект, переданный здесь функции, является Flask объектом запроса , поэтому вам нужно сделать:

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

Я бы рекомендовал переименовать параметр, чтобы он не путался с фоновой функцией :

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'}
...