I am new to Flask/Python and the question might be silly or I might be missing something obvious, so please bear with me.
I have created a Flask app and the structure is as follow:
myproject
api
__init__.py
api.py
application.py
config.py
models.py
migrations
...
appserver.py
manage.py
Procfile
requirements.txt
The contents of my appserver.py
:
from api.application import create_app
if __name__ == '__main__':
create_app = create_app()
create_app.run()
The contents of my api/application.py
:
from flask import Flask
def create_app(app_name='MYAPPNAME'):
app = Flask(app_name)
app.config.from_object('api.config.DevelopmentConfig')
from api.api import api
app.register_blueprint(api, url_prefix='/api')
from api.models import db
db.init_app(app)
return app
When I run my server locally with python appserver.py
everything works as expected. When I try to run gunicorn like so: gunicorn --bind 127.0.0.1:5000 appserver:create_app
I get this error: TypeError: create_app() takes from 0 to 1 positional arguments but 2 were given
What am I doing wrong here?
I would suggest you update the code inside the
appserver.py
files as shown below:and then run the app as follows
gunicorn --bind 127.0.0.1:5000 appserver:gunicorn_app
The reason for the above steps is as follows:
Running the server locally
When you run the server locally with
python appserver.py
theif
block gets executed. Hence the Flask object gets created via yourcreate_app
method and you are able to access the server.Running the server via Gunicorn
When you run the server via Gunicorn, you need to specify the module name and the variable name of the app for Gunicorn to access it. Note that the variable should be a WSGI callable object for e.g a flask app object. This is as per the definition in Gunicorn Docs.
When you were running the Gunicorn command
gunicorn --bind 127.0.0.1:5000 appserver:create_app
, it mistookcreate_app
as the WSGI callable object(Flask app object). This threw the error as create_app is just a regular method which returns the Flask app object on correct invocation.So we added the part of creating the object in the else block
gunicorn_app = create_app()
and called this via the Gunicorn usinggunicorn --bind 127.0.0.1:5000 appserver:gunicorn_app
The other thing that you need to note is when you run
python appserver.py
theif
block gets triggered since it is the main file getting executed. Where as when yougunicorn --bind 127.0.0.1:5000 appserver:create_app
theappserver.py
gets imported by gunicorn. Hence theelse
block gets triggered. This is the reason we have placedgunicorn_app = create_app()
in theelse
block.I hope the above explanation was satisfactory. Let me know if you have not understood any part.