Trying to follow best practices for a Flask app running in Heroku so I'm moving things from app.py to working with blueprints.
The current directory structure is as follows:
--root
--application
--admin_blueprint
--another_blueprint
--wsgi.py (app = create_app())
--__init__.py (this has def create_app, which handles creating my app)
--migration
--Procfile
--requirements.txt
--runtime.txt
--config.py
--manage.py
This is init.py
from flask import Flask
...
def create_app():
app = Flask(...)
...
return app
and this is wsgi.py
from application import create_app
app = create_app()
if __name__ == '__main__':
app.run(host='0.0.0.0')
I cannot for the life of me figure out how to do the Procfile correctly, this is what I previously had when I had app.py and wsgi.py in my root directory and it was working fine on Heroku:
web: gunicorn app:wsgi
I've tried some of these:
web: gunicorn application:wsgi
web: gunicorn application.wsgi
web: gunicorn --pythonpath application application:wsgi
web: gunicorn application.wsgi.py
web: gunicorn "application.wsgi.py"
web: gunicorn "application/wsgi.py"
flask run works because I've exported FLASK_APP=application.wsgi.py
Thank you.
Use application.wsgi:app
application.wsgi (the part before the colon) instructs gunicorn how to resolve the module.
and app (the part after the colon) gives the name of the WSGI application declared in the resolved module.
:app can be omitted and gunicorn defaults to looking in the module for a WSGI application with the name application.
Related
Heroku log is showing: "--- no python application found, check your startup logs for errors ---"
My suspicion is the error within the module under uwsgi.ini file - I've tried multiple different permutations, but haven't been successful.
How can uwsgi.ini file be updated so that heroku can find the app?
Is the structure of my app not ideal for heroku deployment, if so how should I change the structure?
The Flask app has the structure below:
top_dir/
instance/
flask.cfg
sub_dir/
templates/
tests/
static/
users/
form.py
views.py
__init__.py
models.py
run.py
Procfile
uwsgi.ini
requirements.txt
App starts with: python run.py
#run.py
from sub_dir import app
if __name__ == "__main__":
app.run()
This is the code in sub_dir/init.py
from flask import Flask
app = Flask(__name__, instance_relative_config=True)
app.config.from_pyfile('flask.cfg')
#config file in top_dir/instance
Here is the code in the uwsgi.ini file
[uwsgi]
http-socket = :$(PORT)
master = true
die-on-term = true
module = sub_dir:run #error here?
memory-report = true
Procfile
web: uwsgi uwsgi.ini
I use gunicorn --workers 3 wsgi to run my Flask app. If I change the variable application to myapp, Gunicorn gives the error AppImportError: Failed to find application: 'wsgi'. Why am I getting this error and how do I fix it?
myproject.py:
from flask import Flask
myapp = Flask(__name__)
#myapp.route("/")
def hello():
return 'Test!'
if __name__ == "__main__":
myapp.run(host='0.0.0.0')
wsgi.py:
from myproject import myapp
if __name__ == "__main__":
myapp.run()
Gunicorn (and most WSGI servers) defaults to looking for the callable named application in whatever module you point it at. Adding an alias from myproject import myapp as application or application = myapp will let Gunicorn discover the callable again.
However, the wsgi.py file or the alias aren't needed, Gunicorn can be pointed directly at the real module and callable.
gunicorn myproject:myapp --workers 16
# equivalent to "from myproject import myapp as application"
Gunicorn can also call an app factory, optionally with arguments, to get the application object. (This briefly did not work in Gunicorn 20, but was added back in 20.0.1.)
gunicorn 'myproject.app:create_app("production")' --workers 16
# equivalent to:
# from myproject.app import create_app
# application = create_app("production")
For WSGI servers that don't support calling a factory, or for other more complicated imports, a wsgi.py file is needed to do the setup.
from myproject.app import create_app
app = create_app("production")
gunicorn wsgi:app --workers 16
If you're trying to serve an app with variable name app within server/cats.py, you can start the server on port 8000 as follows:
gunicorn server.cats:app -b 0.0.0.0:8000
I have a Flask app I am trying to serve via Gunicorn.
I am using virtualenv and python3. If I activate my venv cd to my app base dir then run:
gunicorn mysite:app
I get:
Starting gunicorn
Listening at http://127.0.0.1:8000
DEBUG:mysite.settings:>>Config()
...
Failed to find application: 'mysite'
Worker exiting
Shutting down: master
Reason: App failed to load
Looking in /etc/nginx/sites-available I only have the file 'default'. In sites-enabled I have no file.
In my nginx.conf file I have:
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
App structure:
mysite #this is where I cd to and run gunicorn mysite:app
--manage.py
--/mysite
----settings.py
----__init__.py
in manage.py for mysite I have following:
logger.debug("manage.py entry point")
app = create_app(app_name)
manager = Manager(app)
if __name__ == "__main__":
manager.run()
In __init__.py file:
def create_app(object_name):
app = Flask(__name__)
#more setup here
return app
In my settings.py in the app directory
class Config(object):
logger.debug(">>Config()") #this logs OK so gunicorn is at least starting in correct directory
From inside the virtualenv if I run
print(sys.path)
I find a path to python and site-packages for this virtualenv.
From what I have read to start gunicorn it's just a matter of installing it and running gunicorn mysite:app
Running gunicorn from the parent directory of mysite I get the same failed to find application: 'mysite', App failed to load error, but don't get the DEBUG...Config() logged (as we are clearly in the wrong directory to start in). Running gunicorn from mysite/mysite (clearly wrong) I get and Exception in worker process ereor, ImportError: No module named 'mysite'.
Any clues as to how I can get gunicorn running?
You're pointing gunicorn at mysite:app, which is equivalent to from mysite import app. However, there is no app object in the top (__init__.py) level import of mysite. Tell gunicorn to call the factory.
gunicorn "mysite:create_app()"
You can pass arguments to the call as well.
gunicorn "mysite:create_app('production')"
Internally, this is equivalent to:
from mysite import create_app
app = create_app('production')
Alternatively, you can use a separate file that does the setup. In your case, you already initialized an app in manage.py.
gunicorn manage:app
I recently changed my Heroku Python Flask app from the 'small application' format to the 'simple package' format based from flask documentation (De-coupling everything in app.py into separate subdirectories)
The application runs correctly using
> python runserver.py
However, executing
gunicorn runserver:app --log-file=-
outputs:
"Starting gunicorn .... connection in use error" (loops forever)
My runserver.py configuration is:
from re3 import app
app.run(debug=True)
__init__.py configuration:
import os
from flask import Flask
from flask import render_template
app = Flask(__name__)
import views
view.py configuration:
from re3 import app
#app.route('/')
def index():
return 'Hello World!'
What is changing in the two executions?
The problem is that you run your application anytime runserver is imported. You only want that to happen when it's executed directly.
from re3 import app
if __name__ == '__main__':
app.run(debug=True)
Edit:
The usage for gunicorn is
$ gunicorn [OPTIONS] APP_MODULE
When you run gunicorn, it imports APP_MODULE. In your case, you've specified runserver. So while you don't import it yourself, gunicorn does. And before gunicorn can run app, runserver runs it.
I use gunicorn --workers 3 wsgi to run my Flask app. If I change the variable application to myapp, Gunicorn gives the error AppImportError: Failed to find application: 'wsgi'. Why am I getting this error and how do I fix it?
myproject.py:
from flask import Flask
myapp = Flask(__name__)
#myapp.route("/")
def hello():
return 'Test!'
if __name__ == "__main__":
myapp.run(host='0.0.0.0')
wsgi.py:
from myproject import myapp
if __name__ == "__main__":
myapp.run()
Gunicorn (and most WSGI servers) defaults to looking for the callable named application in whatever module you point it at. Adding an alias from myproject import myapp as application or application = myapp will let Gunicorn discover the callable again.
However, the wsgi.py file or the alias aren't needed, Gunicorn can be pointed directly at the real module and callable.
gunicorn myproject:myapp --workers 16
# equivalent to "from myproject import myapp as application"
Gunicorn can also call an app factory, optionally with arguments, to get the application object. (This briefly did not work in Gunicorn 20, but was added back in 20.0.1.)
gunicorn 'myproject.app:create_app("production")' --workers 16
# equivalent to:
# from myproject.app import create_app
# application = create_app("production")
For WSGI servers that don't support calling a factory, or for other more complicated imports, a wsgi.py file is needed to do the setup.
from myproject.app import create_app
app = create_app("production")
gunicorn wsgi:app --workers 16
If you're trying to serve an app with variable name app within server/cats.py, you can start the server on port 8000 as follows:
gunicorn server.cats:app -b 0.0.0.0:8000