Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to stop Uvicorn server programmatically?

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?

like image 826
Ömer Alkin Avatar asked Oct 22 '25 03:10

Ömer Alkin


2 Answers

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:

  • os.kill
  • SIGINT
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

like image 119
Snow24 Avatar answered Oct 25 '25 22:10

Snow24


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.

like image 36
MatsLindh Avatar answered Oct 25 '25 21:10

MatsLindh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!