Python3 + GAE + FastAPI it's possible?

186 Views Asked by At

I am migrating an application from python2.7 to python3.10.

And I want to use the FastAPI framework, but I also want to use the legacy Google app engine services https://cloud.google.com/appengine/docs/standard/python3/services/access?hl=pt-br

And I'm getting the following error:

    city.put()
  File "/tmp/tmp7wLPmQ/lib/python3.10/site-packages/google/appengine/ext/ndb/model.py", line 3547, in _put
    return self._put_async(**ctx_options).get_result()
  File "/tmp/tmp7wLPmQ/lib/python3.10/site-packages/google/appengine/ext/ndb/tasklets.py", line 397, in get_result
    self.check_success()
  File "/tmp/tmp7wLPmQ/lib/python3.10/site-packages/google/appengine/ext/ndb/tasklets.py", line 394, in check_success
    six.reraise(self._exception.__class__, self._exception, self._traceback)
  File "/tmp/tmp7wLPmQ/lib/python3.10/site-packages/six.py", line 719, in reraise
    raise value
  File "/tmp/tmp7wLPmQ/lib/python3.10/site-packages/google/appengine/ext/ndb/tasklets.py", line 441, in _help_tasklet_along
    value = gen.throw(exc.__class__, exc, tb)
  File "/tmp/tmp7wLPmQ/lib/python3.10/site-packages/google/appengine/ext/ndb/context.py", line 850, in put
    key = yield self._put_batcher.add(entity, options)
  File "/tmp/tmp7wLPmQ/lib/python3.10/site-packages/google/appengine/ext/ndb/tasklets.py", line 444, in _help_tasklet_along
    value = gen.send(val)
  File "/tmp/tmp7wLPmQ/lib/python3.10/site-packages/google/appengine/ext/ndb/context.py", line 382, in _put_tasklet
    keys = yield self._conn.async_put(options, datastore_entities)
  File "/tmp/tmp7wLPmQ/lib/python3.10/site-packages/google/appengine/datastore/datastore_rpc.py", line 1848, in async_put
    return make_put_call(base_req, pbs, extra_hook)
  File "/tmp/tmp7wLPmQ/lib/python3.10/site-packages/google/appengine/datastore/datastore_rpc.py", line 1828, in make_put_call
    return self._make_rpc_call(config, method, req, resp,
  File "/tmp/tmp7wLPmQ/lib/python3.10/site-packages/google/appengine/datastore/datastore_rpc.py", line 1335, in _make_rpc_call
    rpc = self._create_rpc(config, service_name)
  File "/tmp/tmp7wLPmQ/lib/python3.10/site-packages/google/appengine/datastore/datastore_rpc.py", line 1230, in _create_rpc
    rpc = apiproxy_stub_map.UserRPC(service_name, deadline, callback)
  File "/tmp/tmp7wLPmQ/lib/python3.10/site-packages/google/appengine/api/apiproxy_stub_map.py", line 444, in __init__
    self.__rpc = CreateRPC(service, stubmap)
  File "/tmp/tmp7wLPmQ/lib/python3.10/site-packages/google/appengine/api/apiproxy_stub_map.py", line 69, in CreateRPC
    assert stub, 'No api proxy found for service "%s"' % service
AssertionError: No api proxy found for service "datastore_v3"

My config:

main.py


from google.appengine.ext import ndb


class City(ndb.Model):
    """City fields"""
    db_id = ndb.ComputedProperty(lambda self: self.key.id())
    name = ndb.StringProperty(required=True)
    administrative_area_level_1 = ndb.StringProperty(required=True)
    country = ndb.StringProperty(required=True)
    details = ndb.JsonProperty()

dependencies = []

app = FastAPI()


@app.get("/", tags=["root"])
def read_root():
    return {"Imobzi": "Imobzi APP API"}

@app.post("/v1/post")
def set_post():                                                                                        
    city = City(namespace='')
    city.name = 'Teste'
    city.administrative_area_level_1 = "teste"
    city.country = 'testetim'
    city.put()
    return 'test complete'

@app.get("/v1/post")
def get_post():
    print('\n\n', City.query().fetch())
    return {} 


if __name__ == "__main__":
    uvicorn.run("main:app", host="0.0.0.0", port=8080, reload=True)

app-dev.yaml

runtime: python310
entrypoint: gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app
app_engine_apis: true

env_variables:

  APPLICATION_ID: dev~None
  GOOGLE_APPLICATION_CREDENTIALS: "./app_engine_service_account_dev.json"
  CLOUDSDK_DEVAPPSERVER_PYTHON: /usr/bin/python2.7

bash

#!/bin/bash

HOST=localhost
PY_PATH=python27=/usr/bin/python2.7,python3=/usr/bin/python3

export APPLICATION_ID=dev~None
export GOOGLE_APPLICATION_CREDENTIALS="./app_engine_service_account_dev.json"
export CLOUDSDK_DEVAPPSERVER_PYTHON=/usr/bin/python2.7

python3 ~/google-cloud-sdk/bin/dev_appserver.py \
    --runtime_python_path=$PY_PATH \
app-dev.yaml

Is there any way to make this configuration work?

Use FastApi with GAE bundled services/API

1

There are 1 best solutions below

0
On

TLDR: See this blog article from us

  1. FastAPI is ASGI while GAE bundled APIs only work with WSGI.
  2. To meet your requirements, your App will need to support both WSGI and ASGI. You need to design your App in such a way that calls to use bundled services are on different routes (handled by WSGI) from calls that require use of FastAPI (handled by ASGI)
  3. The earlier referenced blog article explains how to do that and it includes sample code.