__call__() missing 1 required positional argument: 'send' FastAPI on App Engine
Asked Answered
S

5

31

When trying to host an API on App Engine, the following error keeps coming up. The program used to run on Flask which was working but very slow.

Error:

"Traceback (most recent call last):
  File "/env/lib/python3.7/site-packages/gunicorn/workers/sync.py", line 134, in handle
    self.handle_request(listener, req, client, addr)
  File "/env/lib/python3.7/site-packages/gunicorn/workers/sync.py", line 175, in handle_request
    respiter = self.wsgi(environ, resp.start_response)
TypeError: __call__() missing 1 required positional argument: 'send'
"

Docker File:

FROM gcr.io/google_appengine/python

RUN apt-get update && apt-get install -y ffmpeg

# Create a virtualenv for dependencies. This isolates these packages from
# system-level packages.

RUN virtualenv /env -p python3.7

# Setting these environment variables are the same as running
# source /env/bin/activate.

ENV VIRTUAL_ENV /env
ENV PATH /env/bin:$PATH

ADD requirements.txt /app/requirements.txt
RUN pip install -r /app/requirements.txt

# Add the application source code.

ADD . /app

CMD gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app

app.yaml

runtime: custom
env: flex
entrypoint: gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app
service: encoder

runtime_config:
  python_version: 3

handlers:

- url: /.*
  script: auto
Septuplicate answered 15/8, 2020 at 8:24 Comment(3)
The error basically says you are trying to run FastAPI as WSGI which is not right and acceptable because FastAPI is only compatible with ASGI. See thisWalkthrough
Thanks @YagizcanDegirmenci I'll try running it with just UvicornSeptuplicate
So it runs, but now I get this error, "[error] 33#33: *92500 connect() failed (111: Connection refused) while connecting to upstream, client: 216.58.212.244, server: Septuplicate
H
39

As Dustin said I found out that worker class need to be changed. Try the below one.

gunicorn -k uvicorn.workers.UvicornWorker main:app

Found this on github issues

Housemaster answered 14/5, 2021 at 4:11 Comment(1)
That actually is the most direct answer. Thank you for the link.Tombouctou
O
7

App Engine requires your main.py file to declare an app variable which corresponds to a WSGI Application.

Since FastAPI is an asynchronous web framework, it is not compatible with WSGI (which is synchronous).

Your best option would be to use a service like Cloud Run, which would allow you to define your own runtime and use an asynchronous HTTP server compatible with FastAPI.

Occam answered 17/8, 2020 at 18:36 Comment(3)
I am trying to find any info on how to configure Cloud Run to use an asynchronous HTTP server. Can anyone please guide me to the appropriate docs? Thanks.Crosswise
@BellaveJayaram Since Cloud Run allows you to use any container image, there is nothing specific required to use an async HTTP server. If there was a particular server you wanted to use and weren't sure how to get started, I'd recommend asking a new question instead of leaving a comment here.Occam
This is the best answer since it also explains why FastAPI requires a uvicorn worker. Thank you.Boeotian
M
5

I ran into the same issue when I want to deploy a FastAPI app to Heroku. Indeed, you can't use uvicorn (which is the ASGI framework that FastAPI is using) with Heroku that uses gunicorn.

However, by adding a uvicorn worker to gunicorn then it works!:

gunicorn api:app --bind 0.0.0.0:$PORT --worker-class uvicorn.workers.UvicornWorker

Mutualism answered 18/12, 2021 at 14:10 Comment(0)
G
1

In the Starlette code, I found a reference to a2wsgi. And it looks like it is going in both directions (wsgi<>asgi).

I gave it a try and it worked well for me:

from a2wsgi import ASGIMiddleware
wsgi_app = ASGIMiddleware(app)
# use this wsgi instead of your app
Goins answered 7/2, 2023 at 14:2 Comment(1)
You might also add mount call fastapi.tiangolo.com/advanced/wsgi/?h=wsgiCorvine
T
0

I solved it by putting python main.py as the build command and setting my uvicorn command in the main.py as uvicorn.run("main:app", host="0.0.0.0", port=8080)

Tamtama answered 5/8, 2022 at 14:46 Comment(1)
It might works for Google Cloud, but might not work in others settings like pythonanywhere.comCorvine

© 2022 - 2024 — McMap. All rights reserved.