FastAPI throws an error (Error loading ASGI app. Could not import module "api")
Question:
I tried to run FastAPI using uvicorn webserver but it throws an error.
I run this command,
uvicorn api:app --reload --host 0.0.0.0
but there is an error in the terminal.
Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
Started reloader process [23445]
Error loading ASGI app. Could not import module "api".
Stopping reloader process [23445]
Answers:
TL;DR
Add the directory name in front of your filename
uvicorn src.main:app
or cd
into that directory
cd src
uvicorn main:app
Long Answer
It happens because you are not in the same folder with your FastAPI app instance more specifically:
Let’s say i have an app-tree like this;
my_fastapi_app/
├── app.yaml
├── docker-compose.yml
├── src
│ └── main.py
└── tests
├── test_xx.py
└── test_yy.py
$ pwd # Present Working Directory
/home/yagiz/Desktop/my_fastapi_app
I’m not inside the same folder with my app instance, so if I try to run my app with uvicorn I’ll get an error like yours
$ uvicorn main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [40645] using statreload
ERROR: Error loading ASGI app. Could not import module "main".
The answer is so simple, add the folder name in front of your filename
uvicorn src.main:app --reload
or you can change your working directory
cd src
Now i’m inside of the folder with my app instance
src
└── main.py
Run your uvicorn again
$ uvicorn main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [40726] using statreload
INFO: Started server process [40728]
INFO: Waiting for application startup.
INFO: Application startup complete.
I had the same problem and solved it adding package name before main, in your case trying:
uvicorn src.main:app --reload
may solve the problem
This worked for me look at the docs for fastAPI. I am very thankful I ran accross that as the Python script needs to be named main.py
not app.py
The command uvicorn main:app
refers to:
main
: the file main.py
(the Python "module").
app
: the object created inside of main.py
with the line app = FastAPI()
--reload
: make the server restart after code changes. Only use for
development.
One reason this might be happening is that you are using:
uvicorn src/main:app --reload
instead of the correct syntax:
uvicorn src.main:app --reload
Notice the . instead of the /
Currently auto-completion in the terminal suggests the wrong format.
That’s assuming that:
(1) your structure is something like this:
project_folder/
├── some_folder
├── src
│ └── main.py
└── tests
├── test_xx.py
└── test_yy.py
(2) your FastAPI()
object is indeed assigned to an object named app
in main.py
:
app = FastAPI()
(3) you are running the uvicorn command from the project_folder
, e.g.:
(venv) <username>@<pcname>:~/PycharmProjects/project_folder$ uvicorn src.main:app --reload
It seems it is important that you name your file main.py otherwise it won’t work.
Edit: Actually I was running Jupyter Notebook on port 8888 so that port was already occupied. If you have to run Jupyter notebook, run it after running the API server, the notebook will automatically run on 8889.
Alternatively, you can run the API server on a different port.
Hit the Save button in VS Code etc because sometimes it will throw this error if you have not saved the file. Happened to me.
Use this folder structure and configuration where main is in parent directory
launch.json
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: FastAPI",
"type": "python",
"request": "launch",
"module": "uvicorn",
"args": [
"main:app"
],
"jinja": true
}
]
}
main.py
from fastapi import FastAPI
app = FastAPI(
title="test",
description="test",
version="0.0.1",
)
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"main:app",
host="0.0.0.0",
reload=True,
port=3001,
)
Another reason for this error: there is a circular reference between files.
Example:
-
main.py
:
from tools import validator
# ...
class GlobalException(Exception):
# ...
-
/tools/validator.py
:
from main import GlobalException
Also another reason for this error:
There’s already a file named exactly like your running folder, then it will make a conflict to the system.
Example you have a file inside a folder named test_app/main.py
, then you should run uvicorn test_app.main:app --reload
to run the app.
But, if you have a file named test_app.py
(which is the same name as the folder above), it will throw the error when you run the app.
So the solution is to rename the folder or rename the file so they won’t be conflict to each other.
- Step-1 make sure your main file is located in the same directory of your terminal/command prompt, use
ls
command
(virtual-env) shayon@shayon-X556UQK:~/Documents/python-fast-api$ ls
main.py __pycache__ README.md requirements.txt virtual-env
- Step-2 check the directory of your terminal using
pwd
command
(virtual-env) shayon@shayon-X556UQK:~/Documents/python-fast-api$ pwd
/home/shayon/Documents/python-fast-api
- Step-3 check the name of your object – here
app
is the object of FastAPI so we need to use the command uvicorn main:app --reload
, if you keep the object name app1
you need to run uvicorn main:app1 --reload
(virtual-env) shayon@shayon-X556UQK:~/Documents/python-fast-api$ cat main.py
main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def index():
return {"Hello": "World"}
- Step-4 In my case, I made a mistake making command of
uvicorn main.py:app --reload
and this was the reason for my error. The command should be uvicorn main:app --reload
(without dot py extension)
Hope this help – Enjoy 🙂
If you are using Pycharm , the reason could be the source directory not being set correctly. For example, I was trying to configure Python remote debugger using docker-compose and my folder structure was like this:
my_app_name
├── docker-compose.yml
├── src
│ └── main.py
└── tests
├── test_file1.py
└── test_file2.py
I had the src folder inside the root folder, which contained the main.py file. In PyCharm project settings, by default your source folder is set to root.But if you have a nested structure like the case above, you have to go to Preferences->Project->Project Structure->Sources and add your src folder under Source Folders.
For me it was a space problem, I had to delete some files and folders in my system.
I also encountered the same issue,
being a total beginner to FastAPI, the solution given by Yagiz Degirmenci
helped to come up with a simple idea for beginners like me, i.e
cd directory of code
uvicorn fast-api:main --reload
PS. fast-api is the name of my file (i.e fast-api.py)
I fixed this by using the following in my main:
import uvicorn
app = FastAPI()
@app.get("/")
def index():
return {"index": "root"}
if __name__ == '__main__':
uvicorn.run(f"{Path(__file__).stem}:app", host="127.0.0.1", port=8888, reload=True)
and then from the terminal, I typed uvicorn main:app --reload
as my main.py is in my root folder.
don’t give the same name for your python file like uvicorn.py,Folder same name, package name
for me , it’s such stupid : I have main,py
instead of main.py
, and guess what, I uninstall my whole conda env and reinstall pure python3 before I found this…
I tried to run FastAPI using uvicorn webserver but it throws an error.
I run this command,
uvicorn api:app --reload --host 0.0.0.0
but there is an error in the terminal.
Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
Started reloader process [23445]
Error loading ASGI app. Could not import module "api".
Stopping reloader process [23445]
TL;DR
Add the directory name in front of your filename
uvicorn src.main:app
or cd
into that directory
cd src
uvicorn main:app
Long Answer
It happens because you are not in the same folder with your FastAPI app instance more specifically:
Let’s say i have an app-tree like this;
my_fastapi_app/
├── app.yaml
├── docker-compose.yml
├── src
│ └── main.py
└── tests
├── test_xx.py
└── test_yy.py
$ pwd # Present Working Directory
/home/yagiz/Desktop/my_fastapi_app
I’m not inside the same folder with my app instance, so if I try to run my app with uvicorn I’ll get an error like yours
$ uvicorn main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [40645] using statreload
ERROR: Error loading ASGI app. Could not import module "main".
The answer is so simple, add the folder name in front of your filename
uvicorn src.main:app --reload
or you can change your working directory
cd src
Now i’m inside of the folder with my app instance
src
└── main.py
Run your uvicorn again
$ uvicorn main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [40726] using statreload
INFO: Started server process [40728]
INFO: Waiting for application startup.
INFO: Application startup complete.
I had the same problem and solved it adding package name before main, in your case trying:
uvicorn src.main:app --reload
may solve the problem
This worked for me look at the docs for fastAPI. I am very thankful I ran accross that as the Python script needs to be named main.py
not app.py
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.
One reason this might be happening is that you are using:
uvicorn src/main:app --reload
instead of the correct syntax:
uvicorn src.main:app --reload
Notice the . instead of the /
Currently auto-completion in the terminal suggests the wrong format.
That’s assuming that:
(1) your structure is something like this:
project_folder/
├── some_folder
├── src
│ └── main.py
└── tests
├── test_xx.py
└── test_yy.py
(2) your FastAPI()
object is indeed assigned to an object named app
in main.py
:
app = FastAPI()
(3) you are running the uvicorn command from the project_folder
, e.g.:
(venv) <username>@<pcname>:~/PycharmProjects/project_folder$ uvicorn src.main:app --reload
It seems it is important that you name your file main.py otherwise it won’t work.
Edit: Actually I was running Jupyter Notebook on port 8888 so that port was already occupied. If you have to run Jupyter notebook, run it after running the API server, the notebook will automatically run on 8889.
Alternatively, you can run the API server on a different port.
Hit the Save button in VS Code etc because sometimes it will throw this error if you have not saved the file. Happened to me.
Use this folder structure and configuration where main is in parent directory
launch.json
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: FastAPI",
"type": "python",
"request": "launch",
"module": "uvicorn",
"args": [
"main:app"
],
"jinja": true
}
]
}
main.py
from fastapi import FastAPI
app = FastAPI(
title="test",
description="test",
version="0.0.1",
)
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"main:app",
host="0.0.0.0",
reload=True,
port=3001,
)
Another reason for this error: there is a circular reference between files.
Example:
-
main.py
:from tools import validator # ... class GlobalException(Exception): # ...
-
/tools/validator.py
:from main import GlobalException
Also another reason for this error:
There’s already a file named exactly like your running folder, then it will make a conflict to the system.
Example you have a file inside a folder named test_app/main.py
, then you should run uvicorn test_app.main:app --reload
to run the app.
But, if you have a file named test_app.py
(which is the same name as the folder above), it will throw the error when you run the app.
So the solution is to rename the folder or rename the file so they won’t be conflict to each other.
- Step-1 make sure your main file is located in the same directory of your terminal/command prompt, use
ls
command
(virtual-env) shayon@shayon-X556UQK:~/Documents/python-fast-api$ ls
main.py __pycache__ README.md requirements.txt virtual-env
- Step-2 check the directory of your terminal using
pwd
command
(virtual-env) shayon@shayon-X556UQK:~/Documents/python-fast-api$ pwd
/home/shayon/Documents/python-fast-api
- Step-3 check the name of your object – here
app
is the object of FastAPI so we need to use the commanduvicorn main:app --reload
, if you keep the object nameapp1
you need to runuvicorn main:app1 --reload
(virtual-env) shayon@shayon-X556UQK:~/Documents/python-fast-api$ cat main.py
main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def index():
return {"Hello": "World"}
- Step-4 In my case, I made a mistake making command of
uvicorn main.py:app --reload
and this was the reason for my error. The command should beuvicorn main:app --reload
(without dot py extension)
Hope this help – Enjoy 🙂
If you are using Pycharm , the reason could be the source directory not being set correctly. For example, I was trying to configure Python remote debugger using docker-compose and my folder structure was like this:
my_app_name
├── docker-compose.yml
├── src
│ └── main.py
└── tests
├── test_file1.py
└── test_file2.py
I had the src folder inside the root folder, which contained the main.py file. In PyCharm project settings, by default your source folder is set to root.But if you have a nested structure like the case above, you have to go to Preferences->Project->Project Structure->Sources and add your src folder under Source Folders.
For me it was a space problem, I had to delete some files and folders in my system.
I also encountered the same issue,
being a total beginner to FastAPI, the solution given by Yagiz Degirmenci
helped to come up with a simple idea for beginners like me, i.e
cd directory of code
uvicorn fast-api:main --reload
PS. fast-api is the name of my file (i.e fast-api.py)
I fixed this by using the following in my main:
import uvicorn
app = FastAPI()
@app.get("/")
def index():
return {"index": "root"}
if __name__ == '__main__':
uvicorn.run(f"{Path(__file__).stem}:app", host="127.0.0.1", port=8888, reload=True)
and then from the terminal, I typed uvicorn main:app --reload
as my main.py is in my root folder.
don’t give the same name for your python file like uvicorn.py,Folder same name, package name
for me , it’s such stupid : I have main,py
instead of main.py
, and guess what, I uninstall my whole conda env and reinstall pure python3 before I found this…