I want to run FastAPI server using Uvicorn from A different Python file.
uvicornmodule/main.py
import uvicorn
import webbrowser
from fastapi import FastAPI
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
app = FastAPI()
import os
script_dir = os.path.dirname(__file__)
st_abs_file_path = os.path.join(script_dir, "static/")
app.mount("/static", StaticFiles(directory=st_abs_file_path), name="static")
@app.get("/")
async def index():
return FileResponse('static/index.html', media_type='text/html')
def start_server():
# print('Starting Server...')
uvicorn.run(
"app",
host="0.0.0.0",
port=8765,
log_level="debug",
reload=True,
)
# webbrowser.open("http://127.0.0.1:8765")
if __name__ == "__main__":
start_server()
So, I want to run the FastAPI server from the below test.py
file:
from uvicornmodule import main
main.start_server()
Then, I run python test.py
.
But I am getting the below error:
RuntimeError:
An attempt has been made to start a new process before the
current process has finished its bootstrapping phase.
This probably means that you are not using fork to start your
child processes and you have forgotten to use the proper idiom
in the main module:
if __name__ == '__main__':
freeze_support()
...
The "freeze_support()" line can be omitted if the program
is not going to be frozen to produce an executable.
What I am doing wrong? I need to run this module as package.
CodePudding user response:
When spawning new processes from the main process (as this is what happens when uvicorn.run()
is called), it is important to protect the entry point to avoid recursive spawning of subprocesses, etc. As described in this article:
If the entry point was not protected with an if-statement idiom checking for the top-level environment, then the script would execute again directly, rather than run a new child process as expected.
Protecting the entry point ensures that the program is only started once, that the tasks of the main process are only executed by the main process and not the child processes.
Basically, your code that creates the new process must be under if __name__ == '__main__':
. Hence:
from uvicornmodule import main
if __name__ == "__main__":
main.start_server()
Additionally, running uvicorn
programmatically and having reload
and/or workers
flag(s) enabled, you must pass the application as an import string in the format of "<module>:<attribute>"
. For example:
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
As per FastAPI documentation as well:
The command
uvicorn main:app
refers to:
main
: the filemain.py
(the Python "module").app
: the object created inside ofmain.py
with the lineapp = FastAPI()
.--reload
: make the server restart after code changes. Only use for development.