vector8188
vector8188

Reputation: 1393

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 ?

Upvotes: 3

Views: 5780

Answers (2)

W.K.S
W.K.S

Reputation: 10095

If the application is launched using the gunicorn app:app command, then gunicorn will load the app module (app.py) and look for the app variable.

Since the app module is loaded, name will be set to app rather than __main__.

Therefore, a simple fix is:

from module.app import create_app_instance


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

Upvotes: -1

Edo Akse
Edo Akse

Reputation: 4391

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...

Upvotes: 6

Related Questions