App instantiation must occur outside if __name__ == '__main__' block

My code, which was running on Sanic version 22.6.0, no longer works on the latest version of Sanic. It’s giving me an error message saying “App instantiation must occur outside if name == ‘main’ block or by using an AppLoader”. According to the documentation, this change was introduced in version 22.9. Sanic now uses an AppLoader object to create applications in the various worker processes, allowing for a more dynamic startup experience.

Currently, my code uses a create_app function to create an object, which is then run in an if __name__ == '__main__' block. However, it seems like this method is no longer supported in the latest version of Sanic. Is it possible for me to keep using my current method, or do I need to switch to using the AppLoader object?

Thanks

Between LTS versions, the API is subject to change. Unfortunately without an example I’m really unable to answer your question. Can you provide an appropriate code snippet that will illustrate your issue?

from sanic import Sanic
from sanic.response import text


def create_app():
    app = Sanic("MyHelloWorldApp")

    @app.get("/")
    async def hello_world(request):
        return text("Hello, world.")

    return app


if __name__ == "__main__":
    app = create_app()
    app.run(
        host="0.0.0.0",
        port=8000,
    )

For example, in this code, Sanic v22.6.0 is working well. But in Sanic v22.12.0, when I start it, it raised a error
" Sanic app name ‘MyHelloWorldApp’ not found.

App instantiation must occur outside if name == ‘main’ block or by using an AppLoader.

See Dynamic Applications | Sanic Framework for more details."

make the following changes for 22.12 to support the change in the worker functionality

from sanic import Sanic
from sanic.response import text
from sanic.worker.loader import AppLoader
from functools import partial


def create_app():
    try:
        app = Sanic("MyHelloWorldApp")

        @app.get("/")
        async def hello_world(request):
            return text("Hello, world.")

        return app
    except Exception as e:
        print(e)
        exit


if __name__ == "__main__":
    loader = AppLoader(factory=partial(create_app))
    app = loader.load()
    app.prepare(host="0.0.0.0", port=8000, dev=True)
    Sanic.serve(primary=app, app_loader=loader)

I got it. Thank you!

We are going to start changing the documentation over to suggesting developers use the CLI to run Sanic. In a simple example like yours, the CLI would handle the factory pattern fairly easily.

sanic path.to.server:create_app --factory --host=0.0.0.0 --port=8000 --dev

Any way call app.run in a function as before on 22.12? If not, is Flask better? Even ugly FastAPI can do this! My code published after compiled except one main.py outside, the only way to use sanic is app.run in a function called by main.py, but now is gone. Very thanks this awsome project for years.

Thanks! Would be helpful if you had some code to go along with the question.

You can if you intend to only run a single process. If you want multiple workers or any of the multiprocessing features (reload, inspector, etc) then it needs to be run on main process only. Global scope functions run on all processes, which is a problem for multiprocessing.