https://pantsbuild.org/ logo
#general
Title
# general
r

refined-addition-53644

11/01/2022, 7:49 AM
Hi, when running a fastapi application using
./pants run <path_to_main.py>
I get this error
Copy code
ERROR:    Error loading ASGI app. Could not import module "main".
My
main.py
looks like
Copy code
app = FastAPI(title=PROJECT_NAME, debug=DEBUG, version="0.1.0")
app.include_router(v1_router, prefix="/v1")

if __name__ == "__main__":
    uvicorn.run("main:app", host="0.0.0.0", port=9000, reload=True)
This is because fastapi looks for app in the current directory as mentioned here. Even after providing the complete path from pants, it still complains. The only thing which works is when I modify “main:app” to just
app
and remove the reload option completely. It won’t allow just using
app
with
reload=True
Copy code
app = FastAPI(title=PROJECT_NAME, debug=DEBUG, version="0.1.0")
app.include_router(v1_router, prefix="/v1")

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=9000, reload=True)
I am on pants 2.14.0
You can reproduce this using this repo. https://github.com/ShantanuKumar/pants-multi-poetry The main here also has just
app
without any reload.
Copy code
./pants run src/package-a/package_a/main.py
Add
reload=True
in the main and also try with “main:app”.
e

enough-analyst-54434

11/01/2022, 8:18 AM
How about if you instead
./pants package
that
pex_binary
target and then run the pex?
... just to debug what's going wrong here - the
run
implementation or the PEX itself.
s

shy-advantage-49800

11/01/2022, 10:25 AM
I think we already had this conversation on slack before...
I don't recall what was mentioned, but if you search on slack you'll find more info.
Also, given the popularity of FastAPI, it will be cool to write a blog post or add some lines to the documentation to integrate with it. Well, the problem is uvicorn, not FastAPI here...
r

refined-addition-53644

11/01/2022, 10:50 AM
@enough-analyst-54434 I also tried with package and running
pex_binary
. Same issue @shy-advantage-49800 yeah I also think it’s the issue with uvicorn itself.
e

enough-analyst-54434

11/01/2022, 4:41 PM
So, Pants aside - this works. You would need to add a
PYTHONPATH
/
--reload-dir
pair for every relevant source root:
Copy code
$ vi /tmp/src/api.py
$ cat /tmp/src/api.py
import uvicorn
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def read_root():
    return {"Hello": "World!"}

$ pex \
    -D /tmp/src \
    fastapi \
    "uvicorn[standard]" \
    -c uvicorn \
    --inject-arg=api:app \
    -o fastapi.pex
$ PEX_INHERIT_PATH=prefer PYTHONPATH=/tmp/src \
    ./fastapi.pex --port=9000 \
    --reload --reload-dir=/tmp/src &
[1] 2184
$ INFO:     Will watch for changes in these directories: ['/tmp/src']
INFO:     Uvicorn running on <http://127.0.0.1:9000> (Press CTRL+C to quit)
INFO:     Started reloader process [2184] using WatchFiles
INFO:     Started server process [2207]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
$ curl -s <http://127.0.0.1:9000> | jq .
INFO:     127.0.0.1:60370 - "GET / HTTP/1.1" 200 OK
{
  "Hello": "World!"
}
$ vi /tmp/src/api.py
$ WARNING:  WatchFiles detected changes in '/tmp/src/api.py'. Reloading...
INFO:     Shutting down
INFO:     Waiting for application shutdown.
INFO:     Application shutdown complete.
INFO:     Finished server process [2207]
INFO:     Started server process [2267]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

$ curl -s <http://127.0.0.1:9000> | jq .
INFO:     127.0.0.1:60372 - "GET / HTTP/1.1" 200 OK
{
  "Brand": "New",
  "Hello": "World!"
}
$
11 Views