pythongunicornsanic

gunicorn: Failed to find attribute 'app' in module


Hi I am trying to run,

gunicorn --bind localhost:8000 --worker-class sanic_gunicorn.Worker module:app

where I have following files

# ls
build                            
setup.py
dist                             
module         
module.egg-info 
venv

#cd module

#ls
__init__.py
__pycache__
__main__.py
app.py

content of __main__.py is as follows

from module.app import create_app_instance


if __name__ == '__main__':
    app = create_app_instance()
    app.run()

and content of app.py is

#some imports

def create_app_instance():
    app = Sanic(name = "app_name")
    .....
    return app

I am using Sanic web framework and when I am running it's dev server as python -m module it works fine

python3 -m module
[2021-06-16 22:31:36 -0700] [80176] [INFO] Goin' Fast @ http://127.0.0.1:8000
[2021-06-16 22:31:36 -0700] [80176] [INFO] Starting worker [80176]

can someone let me know what am I doing wrong ?


Solution

  • The simple answer is that there's no app exposed inside the module. You have the create_app_instance() method but this is not called.

    I would suggest for you to refactor your code as follows. File structure would be:

    ./wsgi.py
    ./module/__init__.py
    

    And the contents of those files as below:

    .\wsgi.py

    from module import create_app_instance
    
    
    app = create_app_instance()
    
    
    if __name__ == '__main__':
        app.run()
    

    .\module\__init__.py

    # this is the contents of your current app.py
    #some imports
    
    def create_app_instance():
        app = Sanic(name = "app_name")
        .....
        return app
    

    and then the gunicorn line to start the server would be (please note the comment from The Brewmaster below):

    gunicorn --bind localhost:8000 --worker-class sanic_gunicorn.Worker wsgi:app
    

    What this does is it calls the exposed app instance inside wsgi.py. The __main__.py is not needed, and the code from your app.py has been moved to the __init__.py

    I highly advise you to read through documentation/tutorials for Application Factory Pattern for Flask. The principle itself is the same as for Sanic, but there's more articles that describe the principle for Flask...