0

I am a bit confused about best practices when it comes to where and how to initiate the Flask() or FastAPI() for a data-intensive web API. The vast majority of the code available online is using this structure:

app.py

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}

But based on hackersandslackers.com article, this does not seems a good practice:

Notice there's no app.py, main.py, or anything of the sort in our base directory. Instead, the entirety of our app lives in the /application folder, with the creation of our app happening in __init__.py. The init file is where we actually create what's called the Application Factory. If you're wondering how we deploy an app where the main entry point isn't in the root directory, I'm very proud of you. Yes, our app is being created in application/__init__.py, so a file called wsgi.py simply imports this file to serve as our app gateway. More on that another time.

enter image description here

So I did follow hackersandslackers suggestions but I also did a couple of modifications to implement the Factory Pattern on their design. This is my app structure:

src/__ init __.py

from fastapi import FastAPI
from src.api.v1.village import village_router
from src.api.v1.auth import auth_router
from src.core.config import *


def create_app() -> FastAPI:
    root_app = FastAPI()
    root_app.include_router(
        village_router,
        prefix="/api/v1",
        tags=["village"],
    )

    return root_app

src/asgi.py

import uvicorn
from src import create_app

app = create_app()

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", log_level="info", reload=True)

And to run my app I have to type uvicorn asgi:app.

Is that a bad practice to have my create_app() in the __init__.py?

5
  • 1
    "But based on hackersandslackers.com article, this does not seems a good practice" Can you clarify why? The quote you provided does not support your statement. Apr 4 at 16:05
  • sure. Article: Notice there's no app.py, main.py // Other tutorials: app.py Apr 4 at 16:06
  • And from a recent StackOverflow post "The init.py has a different purpose and should rarely contain code." so I am just confused about the best practices for factory pattern Apr 4 at 16:09
  • I still don't follow. Just because they implemented it one way does not mean other ways are bad practices, especially if "[t]he vast majority of the code available online is using [the other] structure". I think this point is important to clarify your question, because it is not clear to me whether you are asking in the general sense whether putting code in __init__.py should be avoided, or whether Flask and FastAPI applications should prefer one or the other structure. Apr 4 at 16:14
  • It's probably a bit too broad but I would prefer to know whether Flask and FastAPI applications should prefer one or the other structure. Apr 4 at 16:16

1 Answer 1

4

I think you are missing an important piece here that I personally found a little confusing when I first encountered it: packages in Python. You can write a lot useful and sophisticated code in Python and never need to use packages. They can be really useful, however, especially if you need to distribute your code to others.

When you create an __init__.py in a directory, you are declaring a package. In your code above, you are creating a package named 'src'. I don't think this is a great name for a package and if you are using packages, I would give it a meaningful name instead. Another thing that you can do in a package is create a __main__.py file. Then you can run your package like python -m mypkg and whatever is in __main__.py will run after the __init__.py completes. If you use pip, for example, it's basically the same as running python -m pip. I actually prefer this way of running pip.

I've used Flask but I'm more familiar with FastAPI so I will focus on the latter. In general, FastAPI doesn't really care whether you structure your code as a package or not. You just need to inform the ASGI application where the FastAPI object is located. If seems to me, however, that the creator of FastAPI prefers using a module named main.py and putting the application object in the main module and name it app. I assert this because if you want to use the container images provided by the author, it will assume main:app is where the application object is located. I wouldn't get too hung up on that, though, because the author also says you probably don't want to use the provided images and recommends you craft your own image instead.

The upshot here is that for FastAPI, I wouldn't bother with packages unless they provide some sort of benefit for your application. Otherwise, I would stick with the main:app because that's the typical convention. But, in general, there's nothing incorrect about putting code in __init__.py. It's a perfect place for initializing the package regardless of how the code is being run. For example, if you want to have modules within your app that can be executed as standalone scripts, using the __init__.py is a good place for common initialization routines and declarations.

3
  • Perfect! Thank you for the answer Apr 5 at 8:07
  • Not sure how common/best practice this is or not, but I also find __init__.py useful for importing objects located deeply in my module structure, so that elsewhere in my code I can write from mypackage import MyObj instead of from mypackage.submodule.subsubmodule.script import MyObj.
    – jfaccioni
    Apr 6 at 13:00
  • @jfaccioni I've started doing this kind of thing recently when there's no obvious module that a 'constant' belongs to.
    – JimmyJames
    Apr 6 at 20:17

Not the answer you're looking for? Browse other questions tagged or ask your own question.