Localhost:如何获取凭据以连接 GAE Python 3 应用程序和数据存储模拟器?

Localhost: how to get credentials to connect GAE Python 3 app and Datastore Emulator?

我想在 localhost 上将新的数据存储模拟器与 GAE Flask 应用程序一起使用。我想在 Docker 环境中 运行 它,但是我得到的错误 (DefaultCredentialsError) 在有或没有 Docker.

的情况下都会发生

我的 Flask 文件如下所示 (see the whole repository here on GitHub):

main.py:

from flask import Flask
from google.cloud import datastore


app = Flask(__name__)


@app.route("/")
def index():
    return "App Engine with Python 3"


@app.route("/message")
def message():
    # auth
    db = datastore.Client()

    # add object to db
    entity = datastore.Entity(key=db.key("Message"))
    message = {"message": "hello world"}
    entity.update(message)
    db.put(entity)

    # query from db
    obj = db.get(key=db.key("Message", entity.id))

    return "Message for you: {}".format(obj["message"])

index() 处理程序工作正常,但 message() 处理程序抛出此错误:

[2019-02-03 20:00:46,246] ERROR in app: Exception on /message [GET]
Traceback (most recent call last):
  File "/tmp/tmpJcIw2U/lib/python3.5/site-packages/flask/app.py", line 2292, in wsgi_app
    response = self.full_dispatch_request()
  File "/tmp/tmpJcIw2U/lib/python3.5/site-packages/flask/app.py", line 1815, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/tmp/tmpJcIw2U/lib/python3.5/site-packages/flask/app.py", line 1718, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/tmp/tmpJcIw2U/lib/python3.5/site-packages/flask/_compat.py", line 35, in reraise
    raise value
  File "/tmp/tmpJcIw2U/lib/python3.5/site-packages/flask/app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
  File "/tmp/tmpJcIw2U/lib/python3.5/site-packages/flask/app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/app/main.py", line 16, in message
    db = datastore.Client()
  File "/tmp/tmpJcIw2U/lib/python3.5/site-packages/google/cloud/datastore/client.py", line 210, in __init__
    project=project, credentials=credentials, _http=_http
  File "/tmp/tmpJcIw2U/lib/python3.5/site-packages/google/cloud/client.py", line 223, in __init__
    _ClientProjectMixin.__init__(self, project=project)
INFO     2019-02-03 20:00:46,260 module.py:861] default: "GET /message HTTP/1.1" 500 291
  File "/tmp/tmpJcIw2U/lib/python3.5/site-packages/google/cloud/client.py", line 175, in __init__
    project = self._determine_default(project)
  File "/tmp/tmpJcIw2U/lib/python3.5/site-packages/google/cloud/datastore/client.py", line 228, in _determine_default
    return _determine_default_project(project)
  File "/tmp/tmpJcIw2U/lib/python3.5/site-packages/google/cloud/datastore/client.py", line 75, in _determine_default_project
    project = _base_default_project(project=project)
  File "/tmp/tmpJcIw2U/lib/python3.5/site-packages/google/cloud/_helpers.py", line 186, in _determine_default_project
    _, project = google.auth.default()
  File "/tmp/tmpJcIw2U/lib/python3.5/site-packages/google/auth/_default.py", line 306, in default
    raise exceptions.DefaultCredentialsError(_HELP_MESSAGE)
google.auth.exceptions.DefaultCredentialsError: Could not automatically determine credentials. Please set GOOGLE_APPLICATION_CREDENTIALS or explicitly create credentials and re-run the application. For more information, please see https://cloud.google.com/docs/authentication/getting-started

我检查了错误日志中的网站并尝试了 JSON 授权文件 (GOOGLE_APPLICATION_CREDENTIALS),但结果是我的应用程序随后连接到 production Google 云上的数据存储,而不是本地数据存储模拟器。

知道如何解决这个问题吗?

需要凭据这一事实表明您正在访问实际的数据存储,而不是数据存储模拟器(它既不需要也不请求凭据)。

要访问模拟器,客户端应用程序(支持它)需要弄清楚模拟器正在侦听的位置,为此,您需要为它们设置 DATASTORE_EMULATOR_HOST 环境变量。来自 Setting environment variables:

After you start the emulator, you need to set environment variables so that your application connects to the emulator instead of the production Datastore mode environment. Set these environment variables on the same machine that you use to run your application.

You need to set the environment variables each time you start the emulator. The environment variables depend on dynamically assigned port numbers that could change when you restart the emulator.

请参阅该部分的其余部分,了解有关设置环境的详细信息,也许可以查看

我设法通过将环境变量直接添加到 Python 代码(在本例中是 main.py 中)并使用 Mock 库解决了这个问题:

import os

import mock
from flask import Flask, render_template, request
from google.cloud import datastore
import google.auth.credentials


app = Flask(__name__)

if os.getenv('GAE_ENV', '').startswith('standard'):
    # production
    db = datastore.Client()
else:
    # localhost
    os.environ["DATASTORE_DATASET"] = "test"
    os.environ["DATASTORE_EMULATOR_HOST"] = "localhost:8001"
    os.environ["DATASTORE_EMULATOR_HOST_PATH"] = "localhost:8001/datastore"
    os.environ["DATASTORE_HOST"] = "http://localhost:8001"
    os.environ["DATASTORE_PROJECT_ID"] = "test"

    credentials = mock.Mock(spec=google.auth.credentials.Credentials)
    db = datastore.Client(project="test", credentials=credentials)

Datastore 模拟器然后 运行 像这样:

gcloud beta emulators datastore start --no-legacy --data-dir=. --project test --host-port "localhost:8001"

所需要求:

Flask
google-cloud-datastore
mock
google-auth

GitHub 此处示例:https://github.com/smartninja/gae-2nd-gen-examples/tree/master/simple-app-datastore