FastAPI python app error on Azure App Service - python

I have a python web application that is using FastAPI. It works locally, but when I deploy it to a free linux Azure App Service (using GitHub Actions) and try to load the site it says "Internal Server Error". When I pull up the application logs I see the following error message
2023-02-06T23:44:30.765055894Z [2023-02-06 23:44:30 +0000] [90] [ERROR] Error handling request /
2023-02-06T23:44:30.765101490Z Traceback (most recent call last):
2023-02-06T23:44:30.765109589Z File "/opt/python/3.10.9/lib/python3.10/site-packages/gunicorn/workers/sync.py", line 136, in handle
2023-02-06T23:44:30.765116389Z self.handle_request(listener, req, client, addr)
2023-02-06T23:44:30.765122088Z File "/opt/python/3.10.9/lib/python3.10/site-packages/gunicorn/workers/sync.py", line 179, in handle_request
2023-02-06T23:44:30.765128688Z respiter = self.wsgi(environ, resp.start_response)
2023-02-06T23:44:30.765134688Z TypeError: FastAPI.__call__() missing 1 required positional argument: 'send'
Any suggestions on how to fix this issue?

I was able to resolve this issue by adding the following custom startup command in the Azure App Service Configuration General Settings
python -m uvicorn app:app --host 0.0.0.0
As h4z3 pointed out, gunicorn is wsgi and fastapi is asgi so I had to change the startup command to use uvicorn. Additional details can be found in the Azure docs here: https://learn.microsoft.com/en-us/azure/app-service/configure-language-python#example-startup-commands

Related

Gunicorn + Flask + Docker python app hosted on Azure Container Instances returns SystemExit: 1

I deployed a web app on GPU enabled ACI (Azure Container Instance) using Gunicorn + Flask + Docker. This app runs a couple of pytorch models (one of them being easyOCR and the other being YOLOv5).
The app was working fine, but then started to throw exception for all incoming requests. similar to the following
File "/usr/local/lib/python3.7/site-packages/werkzeug/wrappers/request.py", line 540, in json
return self.get_json()
File "/usr/local/lib/python3.7/site-packages/werkzeug/wrappers/request.py", line 575, in get_json
data = self.get_data(cache=cache)
File "/usr/local/lib/python3.7/site-packages/werkzeug/wrappers/request.py", line 405, in get_data
rv = self.stream.read()
File "/usr/local/lib/python3.7/site-packages/gunicorn/http/body.py", line 215, in read
data = self.reader.read(1024)
File "/usr/local/lib/python3.7/site-packages/gunicorn/http/body.py", line 130, in read
data = self.unreader.read()
File "/usr/local/lib/python3.7/site-packages/gunicorn/http/unreader.py", line 37, in read
d = self.chunk()
File "/usr/local/lib/python3.7/site-packages/gunicorn/http/unreader.py", line 64, in chunk
return self.sock.recv(self.mxchunk)
File "/usr/local/lib/python3.7/site-packages/gunicorn/workers/base.py", line 203, in handle_abort
sys.exit(1)
SystemExit: 1
gunicorn parameters
gunicorn wsgi:app --bind 0.0.0.0:443 --log-level=info --workers=3 --reload --timeout 120
ACI specs
4 Cores
8 GB RAM
1 GPU Tesla K80
Linux environment
Followed this blog to create the app.
I tried adjusting the timeout parameter following many other posts such as this but didn't resolve the issue.
What caused this error and how do I fix this?
Thank you #amro_ghoneim for updating the resolution in the comments. Posting it as an answer to help other community members.
To get rid of those exceptions, change worker type to gevent.
To pause your application code for extended periods of time make use of gevent worker or -k gevent on the command line.
In order to add gevent worker, add below commands in your config file:
pip install gevent
gunicon .... --worker-class gevent
Reference :
Gunicorn worker timeout error - Stack Overflow

Deploying a Quart Python app in Google App Engine

I'm trying to deploy a Quart based python app via Google Cloud's App Engine Standard. However, I keep getting the following error:
Traceback (most recent call last):
File "/env/lib/python3.7/site-packages/gunicorn/workers/gthread.py", line 284, in handle
keepalive = self.handle_request(req, conn)
File "/env/lib/python3.7/site-packages/gunicorn/workers/gthread.py", line 333, in handle_request
respiter = self.wsgi(environ, resp.start_response)
TypeError: __call__() missing 1 required positional argument: 'send'
I know that Quart is an ASGI solution and Google App Engine is a Serverless setting. One of the recommendations for deploying quart into AWS Lambda was to use Magnum. Does that work for Google Cloud App Engine as well?
Any help would be appreciated.
From https://github.com/pgjones/quart/issues/68:
Quart is an ASGI framework, rather than a WSGI framework, which means that it cannot work with serverless. It can work with Mangum, which is an ASGI alternative to serverless.
This also means that Quart will not be compatible with App Engine, Cloud Functions, etc.
However, it would work well with Cloud Run via a HTTP server that supports ASGI such as Uvicorn.
Magnum is an adapter for using ASGI applications with AWS Lambda & API Gateway and is not tested for Google GCP.
I recommend following the suggestion of #di and use Uvicorn with Cloud Run.

Is it possible to run flask without port? [duplicate]

This question already has answers here:
Are a WSGI server and HTTP server required to serve a Flask app?
(3 answers)
How do I get Flask to run on port 80?
(15 answers)
Closed 4 years ago.
I tried to launche Flask in hosting using:
if __name__ == "__main__":
app.run('0.0.0.0', 8000)
But hoster has 8080 port as closed, it is possible to run Flask with default port 80?
I tried it gives me this error:
Use a production WSGI server instead.
* Debug mode: off
Traceback (most recent call last):
File "__init__.py", line 461, in <module>
app.run('0.0.0.0', 80)
File "/home/o/oliwin4/project/public_html/myenv/local/lib/python2.7/site-packages/flask/app.py", line 943, in run
run_simple(host, port, self, **options)
File "/home/o/oliwin4/project/public_html/myenv/local/lib/python2.7/site-packages/werkzeug/serving.py", line 814, in run_simple
inner()
File "/home/o/oliwin4/project/public_html/myenv/local/lib/python2.7/site-packages/werkzeug/serving.py", line 774, in inner
fd=fd)
File "/home/o/oliwin4/project/public_html/myenv/local/lib/python2.7/site-packages/werkzeug/serving.py", line 660, in make_server
passthrough_errors, ssl_context, fd=fd)
File "/home/o/oliwin4/project/public_html/myenv/local/lib/python2.7/site-packages/werkzeug/serving.py", line 577, in __init__
self.address_family), handler)
File "/usr/lib/python2.7/SocketServer.py", line 419, in __init__
self.server_bind()
File "/usr/lib/python2.7/BaseHTTPServer.py", line 108, in server_bind
SocketServer.TCPServer.server_bind(self)
File "/usr/lib/python2.7/SocketServer.py", line 430, in server_bind
self.socket.bind(self.server_address)
File "/usr/lib/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 1] Operation not permitted
So, hoster said tht 80 port is open.
The Flask documentation states that:
While lightweight and easy to use, Flask’s built-in server is not
suitable for production as it doesn’t scale well. Some of the options
available for properly running Flask in production are documented
here.
The documentation also states several methods of using WSGI servers to deploy your web application. WSGI (Web Server Gateway Interface) is a standard that forwards requests from web servers to web applications written in Python. You'll want to use a WSGI server to run your website on your host, since it sounds like you're trying to deploy a Flask app to a production setting.
To answer your original question, the Flask library intentionally throws an error when you try to run it on port 80, because they specifically say that you should not use Flask's built-in server for production use. That's this part of your stacktrace:
Use a production WSGI server instead.
* Debug mode: off
and
socket.error: [Errno 1] Operation not permitted
For the lazy, or if the above link goes dead, here is an example using Gunicorn (copied directly from the above documentation link)
Gunicorn
Gunicorn ‘Green Unicorn’ is a WSGI HTTP Server for UNIX. It’s a
pre-fork worker model ported from Ruby’s Unicorn project. It supports
both eventlet and greenlet. Running a Flask application on this server
is quite simple:
gunicorn myproject:app
Gunicorn provides many command-line options – see gunicorn -h. For
example, to run a Flask application with 4 worker processes (-w 4)
binding to localhost port 4000 (-b 127.0.0.1:4000):
gunicorn -w 4 -b 127.0.0.1:4000 myproject:app

Endpoints quickstart-app-engine for Python deploy error

I'm trying to following the step-by-step tutorial found here, but the deploy just does not work, always returning Error Response: [13] An internal error occurred.
I did not change anything in the example code itself. As I said, I just followed the linked tutorial carefully. It fails and return the error above when I try gcloud app deploy.
Using gcloud app deploy --verbosity debug it brings some stacktrace, but without any usefull meaning. I'm copying below for completeness:
Updating service [default] (this may take several minutes)...failed.
DEBUG: (gcloud.app.deploy) Error Response: [13] An internal error occurred
Traceback (most recent call last):
File "/Users/jamesmiranda/Documents/google-cloud-sdk/lib/googlecloudsdk/calliope/cli.py", line 791, in Execute
resources = calliope_command.Run(cli=self, args=args)
File "/Users/jamesmiranda/Documents/google-cloud-sdk/lib/googlecloudsdk/calliope/backend.py", line 756, in Run
resources = command_instance.Run(args)
File "/Users/jamesmiranda/Documents/google-cloud-sdk/lib/surface/app/deploy.py", line 65, in Run
parallel_build=False)
File "/Users/jamesmiranda/Documents/google-cloud-sdk/lib/googlecloudsdk/command_lib/app/deploy_util.py", line 587, in RunDeploy
flex_image_build_option=flex_image_build_option)
File "/Users/jamesmiranda/Documents/google-cloud-sdk/lib/googlecloudsdk/command_lib/app/deploy_util.py", line 395, in Deploy
extra_config_settings)
File "/Users/jamesmiranda/Documents/google-cloud-sdk/lib/googlecloudsdk/api_lib/app/appengine_api_client.py", line 188, in DeployService
message=message)
File "/Users/jamesmiranda/Documents/google-cloud-sdk/lib/googlecloudsdk/api_lib/app/operations_util.py", line 244, in WaitForOperation
sleep_ms=retry_interval)
File "/Users/jamesmiranda/Documents/google-cloud-sdk/lib/googlecloudsdk/api_lib/util/waiter.py", line 266, in WaitFor
sleep_ms=sleep_ms)
File "/Users/jamesmiranda/Documents/google-cloud-sdk/lib/googlecloudsdk/core/util/retry.py", line 222, in RetryOnResult
if not should_retry(result, state):
File "/Users/jamesmiranda/Documents/google-cloud-sdk/lib/googlecloudsdk/api_lib/util/waiter.py", line 260, in _IsNotDone
return not poller.IsDone(operation)
File "/Users/jamesmiranda/Documents/google-cloud-sdk/lib/googlecloudsdk/api_lib/app/operations_util.py", line 169, in IsDone
encoding.MessageToPyValue(operation.error)))
OperationError: Error Response: [13] An internal error occurred
ERROR: (gcloud.app.deploy) Error Response: [13] An internal error occurred
Below is the app.yaml (exactly tha same of example git, except for the APPID):
runtime: python
env: flex
entrypoint: gunicorn -b :$PORT main:app
runtime_config:
python_version: 3
# [START configuration]
endpoints_api_service:
# The following values are to be replaced by information from the output of
# 'gcloud endpoints services deploy openapi-appengine.yaml' command.
name: echo-api.endpoints.MYAPPID.cloud.goog
config_id: [2018-01-09r1]
# [END configuration]
What I tried until now:
Change python version to python 2 (python_version: 2);
Include some files to skip in the app.yaml (copied from endpoint framework in standard env tutorial);
skip_files:
- ^(.*/)?#.*#$
- ^(.*/)?.*~$
- ^(.*/)?.*\.py[co]$
- ^(.*/)?.*/RCS/.*$
- ^(.*/)?\..*$
- ^(.*/)?setuptools/script \(dev\).tmpl$
Tried the workaround from here;
gcloud config set app/use_deprecated_preparation True
NOthing worked. What I'm doing wrong?
Notes:
It works fine locally following the README info;
Everything works in GAE standard env folowing this another tutorial;
I did not found any problem in the Endpoint itself (I can see it deployed in API explorer), but the app deploy did not work in any way.
If the app.yaml file you are using is exactly the same as the one you copied in your question then there seems to be an error in the name and config-id you are entering. With the info provided in your question your app.yaml should look like:
runtime: python
env: flex
entrypoint: gunicorn -b :$PORT main:app
runtime_config:
python_version: 3
# [START configuration]
endpoints_api_service:
# The following values are to be replaced by information from the output of
# 'gcloud endpoints services deploy openapi-appengine.yaml' command.
name: "echo-api.endpoints.MYAPPID.cloud.goog"
config_id: "2018-01-09r1"
# [END configuration]
See that you were not entering the values for name and config_id inside quotation marks, and also you should not enter your config_id inside brackets.
I have tried this myself and works alright. If it still doesn't work for you maybe your name is not correct, as the format seems to be:
"example-project.appspot.com"
So if your project id is i.e. my-project-id, then your name would look like:
"my-project-id.appspot.com"

cherrypy https script not working with linux startup

Trying to run a cherrypy https server on linux startup. The startup script works with cherrypy running http, but not https. Also, when running https server manually it works, so no library issues there. The summary and error is below:
https and http server are working when running it manually on linux
http is working on linux startup
https is not working on linux startup
I output the results of the https startup script to a text file, and this error is encountered:
[25/Feb/2015:13:59:03] ENGINE Bus STARTING
[25/Feb/2015:13:59:03] ENGINE Started monitor thread '_TimeoutMonitor'.
[25/Feb/2015:13:59:03] ENGINE Started monitor thread 'Autoreloader'.
[25/Feb/2015:13:59:03] ENGINE Serving on 0.0.0.0:8099
[25/Feb/2015:13:59:03] ENGINE Bus STARTED
[25/Feb/2015:13:59:03] ENGINE Error in HTTPServer.tick
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/cherrypy/wsgiserver/wsgiserver2.py", line 1837, in start
self.tick()
File "/usr/local/lib/python2.7/site-packages/cherrypy/wsgiserver/wsgiserver2.py", line 1902, in tick
s, ssl_env = self.ssl_adapter.wrap(s)
File "/usr/local/lib/python2.7/site-packages/cherrypy/wsgiserver/ssl_builtin.py", line 52, in wrap
keyfile=self.private_key, ssl_version=ssl.PROTOCOL_SSLv23)
File "/usr/local/lib/python2.7/ssl.py", line 387, in wrap_socket
ciphers=ciphers)
File "/usr/local/lib/python2.7/ssl.py", line 141, in __init__
ciphers)
SSLError: [Errno 336265218] _ssl.c:351: error:140B0002:SSL routines:SSL_CTX_use_PrivateKey_file:system lib
I set the permissions on the folder containing the script to "chmod 777", i.e. grant all permissions to all users/groups. No luck.
You are most likely setting a relative path to the certificate or maybe it does not have read permission.
Double check the path to the certificate. Use an absolute one and keep an eye for any required escape character. \
Fixed the solution, cyraxjoe is right. It ended up being the init.d script was running the python server file from etc/init.d/, and the private key file was using a relative path. Using the absolute path ended up solving the problem.
Thanks!!!

Categories