I try to set a Flask application in AWS EB and I am running on this issue on the Log.
Failed to find attribute 'application' in 'app'.
My application is using Application factory, so the init are set in the function.
def create_app(config_name):
app = Flask(__name__)
from .api.routes import api
app.register_blueprint(api, url_prefix="/api/v1")
from .main import main
app.register_blueprint(main)
app.run()
return app
I have changed the WSGIPath to match my application name and object:
aws:elasticbeanstalk:container:python:
NumProcesses: '1'
NumThreads: '15'
WSGIPath: app
My application structure looks like this:
__init__.py(empty)
app.py
main.py
requirements.txt
api/
__init___.py (empty)
routes.py
What am I missing ? I am feeling so close and so far away at the same time.
Thanks for your help.
Elastic beanstalk expects your app.py to be named application.py. Also, change
app = Flask(__name__) to application = app = Flask(__name__)
Related
I was deploying a flask applications to Azure App Services with the following (example) file structure.
flask-app
├── application.py
└── web
└── __init__.py
Inside __init__.py I declared app = Flask(__name__) (and of course do other things such as setup the configuration and add the controllers). Then, inside application.py, I just did from web import app.
When attempting to deploying this to Azure App Services, I would receive the following error when App Services would try to start the application: "Failed to find attribute 'app' in 'application'".
In order to fix this, I modified application.py to do the following:
from web import app
app = app
And then the app was able to be deployed. Of course, I'm somewhat skeptical that this is a proper fix or if what was happening was a bug, but I thought I would share this in case it helped others in the future.
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.
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 successfully deployed the app and ran the url its shows application error.
Checked the Log, it states:
* Running on http://127.0.0.1:5000/
Web process failed to bind to $PORT within 60 seconds of launch
Procfile
web: python run.py ${PORT}
run.py
from app import app
app.run(debug=False)
I also tried with
from os import environ
from app import app
app.run(debug=False, port=environ.get("PORT", 5000), processes=2)
In both the case the error still persist
views.py
#app.route('/')
#app.route('/login', methods=["GET","POST"])
def login():
....
That's really not how you run a Flask application in production. You need an actual server, such as gunicorn, and you point that to your app object:
web: gunicorn app:app
This is all fully explained in the Heroku tutorial.
My Python web application is called app
# example.py
import flask
app = flask.Flask(__name__.split('.')[0])
and when I attempt to launch it on AWS-EB using
# run.py (set correctly with WSGIPath)
from example import app
if __name__ == "__main__":
app.run()
I get
mod_wsgi (pid=22473): Target WSGI script '/opt/python/current/app/run.py'
does not contain WSGI application 'application'.
How to I tell AWS that my application instance is called app?
mod_wsgi expects variable called application. Try to do something like this
from example import app as application
Note: don't do application.run(). It is not needed.
While the WSGIPath can be configured. Beanstalk still expects the app variable to be named as 'application'.
A simple workaround for small single file python apps can be
from flask import Flask
app = Flask(__name__)
application = app # For beanstalk
You can keep the rest of the code as is. You just need to add that single line application = app