2

In Docker, I run uvicorn with bootstrap.sh & command line. In code there is a condition about public key file, if exception occurs, server needs to shutdown.

So what I want to do in main.py is here (It is FastAPI).

public_key = None

try:
    with open(PUBLIC_KEY_FILE) as public_key_file:
        public_key = public_key_file.read()
except Exception as f_error:
    logger.exception(f_error)
    module = util.find_spec("uvicorn")

    if module:
        uvicorn = import_module('uvicorn')
        uvicorn.stop() # what I want to do

However, I couldn't find a way to shutdown uvicorn server programmatically. What would be the best approach?

Ömer Alkin
  • 163
  • 3
  • 17
  • 1
    Raising an exception (or re-raising `f_error`) inside your `except` clause would terminate the current application unless there's another level of exception handling outside of this code. Would that work? – MatsLindh May 05 '21 at 13:02
  • @MatsLindh Yes it works and it actually a quite good work around, thank you! – Ömer Alkin May 05 '21 at 14:21
  • Does this answer your question? [How to start a Uvicorn + FastAPI in background when testing with PyTest](https://stackoverflow.com/questions/57412825/how-to-start-a-uvicorn-fastapi-in-background-when-testing-with-pytest) – Wolfgang Fahl Aug 27 '22 at 08:37
  • duplicate of https://stackoverflow.com/q/57412825/1032286 – Wolfgang Fahl Aug 27 '22 at 08:37

3 Answers3

1

Raising an exception (or re-raising f_error) inside your except clause would terminate the current application unless there's another level of exception handling outside of the code you've included.

When the python interpreter receives a top level exception (i.e. one that isn't caught by except), the interpreter terminates. You can use this to shut down your script and trigger your container runtime to restart the application as necessary.

MatsLindh
  • 49,529
  • 4
  • 53
  • 84
1

I need to terminate the backend FastAPI service when an environment variable is missing. With gunicorn I use sys.exit(4):

try:
   DB_CONN = os.environ["DB_CONN"]

except Exception as e:
   print(f"Missing env variable value for {e}. Terminating.")
   sys.exit(4)

Here is the result in Docker:

enter image description here

Alex Protyagov
  • 511
  • 6
  • 6
1

Gracefully Shutting Down Uvicorn running FastAPI Application

The key libraries to achieve graceful shutting down to a Uvicorn server running a FastAPI application are the built in os and signal modules. Given an endpoint with which a client can request the server to shutdown.

os.kill(os.getpid(), signal.SIGINT)

os.getpid() retrieves the running process' system ID and then signal.SIGINT is passed to the process to signal an interrupt. SIGTERM and SIGINT can be used to achieve the same result.

Links:

import os
import signal
import fastapi
import uvicorn

app = fastapi.FastAPI()

def hello():
    return fastapi.Response(status_code=200, content='Hello, world!')

def shutdown():
    os.kill(os.getpid(), signal.SIGTERM)
    return fastapi.Response(status_code=200, content='Server shutting down...')

@app.on_event('shutdown')
def on_shutdown():
    print('Server shutting down...')

app.add_api_route('/hello', hello, methods=['GET'])
app.add_api_route('/shutdown', shutdown, methods=['GET'])

if __name__ == '__main__':
    uvicorn.run(app, host='localhost', port=8000)
import requests

if __name__ == '__main__':
    print(requests.get('http://localhost:8000/hello').content)
    print(requests.get('http://localhost:8000/shutdown').content)

https://gist.github.com/BnJam/8123540b1716c81922169fa4f7c43cf0

Snow24
  • 317
  • 3
  • 11