Why when I start uvicorn in my FastAPI service does my configuration method run twice?

Viewed 1777

I have written a service using fastapi and uvicorn. I have a main in my service that starts uvicorn (see below). In that main, the first thing I do is load configuration settings. I have some INFO outputs that output the settings when I load the configuration. I notice when I start my service, the configuration loading method seems to be running twice.

# INITIALIZE
if __name__ == "__main__":
    # Load the config once at bootstrap time. This outputs the string "Loading configuration settings..."
    config = CdfAuthConfig()
    print("Loaded Configuration")
    # Create FastAPI object
    app = FastAPI()
    # Start uvicorn
    uvicorn.run(app, host="127.0.0.1", port=5050)

The output when I run the service looks like:

Loading configuration settings...
Loading configuration settings...
Loaded Configuration

Why is the "CdfAuthConfig()" class being instantiated twice? It obviously has something to do with the "uvicorn.run" command.

1 Answers

I had a similar setup and this behavior made me curious, I did some tests and now I see probably why.

Your if __name__ == "__main__": is being reached only once, this is a fact.

How can you test this. Add the following line before your if:

 print(__name__)

If you run your code as is, but adding the line I mentioned, it will print:

__main__  # in the first run

Then uvicorn will call your program again and will print something like:

__mp_main__  # after uvicorn starts your code again

And right after it will also print:

app  # since this is the argument you gave to uvicorn

If you want to avoid that, you should call uvicorn from the command line, like:

uvicorn main:app --reload --host 0.0.0.0 --port 5000  # assuming main.py is your file name

uvicorn will reload your code since you are calling it from inside the code. Maybe a work around would be to have the uvicorn call in a separate file, or as I said, just use the command line. If you don't wanna write the command with the arguments all the time, you can write a small script (app_start.sh)

I hope this helps you understand a little bit better.

Related