I'm deploying a simple Flask app to Heroku - (first time using Flask and Heroku both). When I try to deploy, I get an "Application Error" and the page tells me to try again in a few minutes. The logs state - the "connection [is] in use", retries a few times and then the worker exits (I can post the logs if that is helpful).
My demo.py file:
import flask, flask.views
import os
import urllib2
from bs4 import BeautifulSoup
opener = urllib2.build_opener()
app = flask.Flask(__name__)
app.secret_key = "bacon"
class View(flask.views.MethodView):
def get(self):
return flask.render_template('index.html')
def post(self):
url = (flask.request.form['url'])
ourUrl = opener.open(url).read()
soup = BeautifulSoup(ourUrl)
title = soup.title.text
recipe = soup.find("div", {"id": "recipe"}).getText()
flask.flash(title)
flask.flash(recipe)
return self.get()
app.add_url_rule('/', view_func=View.as_view('main'), methods=['GET', 'POST'])
app.debug = True
app.run()
My procfile is:
web: gunicorn demo:app
If I change the procfile to web: python demo.py, I am able to run the app locally using Foreman but still cannot deploy to Heroku.
Any help is very much appreciated. This is my first time doing this!!
Thank you.
I figured it out. Need to add the following before app.run()
if __name__ == "__main__":
Now it runs fine on Heroku.
Related
I'm attempting to host a basic python app on a domain that I purchased through Namecheap and it's being hosted on cPanel. I've followed this tutorial word for word, however I'm receiving this 500 error (image below) and I can't seem to figure it out. Anyone have any suggestions on how to solve this issue? Thank you!
This is my app.py file:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello World!"
#app.route("/<string:name>/")
def say_hello(name):
return "Hello {name}!"
if __name__ == "__main__":
app.run()
This is my passenger_wsgi.py file:
from app import app as application
Usecase: I have a python flask app that runs background_function() before serving any requests on routes.
When I execute the flask app, I receive the error - RuntimeError: Working outside of application context. I receive the error since I try to get the application context before any request is served.
What is the best pythonic way to execute the background_function() in this example?
from flask import Flask
from download import Download
app = Flask(__name__)
app.config.from_pyfile('config.py')
# run backgroung function
Download.background_function()
#app.route('/')
def index():
return 'Welcome!'
if __name__ == '__main__':
app.run()
The config file
FILE_LOCATION = os.environ['FILE_LOCATION'] # "file/path/on/server"
# Many other variables are present in this file
The download file
from flask import current_app as app
class Download:
#staticmethod
def background_function():
file_path = app.config["FILE_LOCATION"]
# code to download file from server to local
return
Try this:
from flask import Flask
from download import Download
app = Flask(__name__)
#app.route('/')
def index():
return 'Welcome!'
if __name__ == '__main__':
Download.background_function()
app.run()
the download file
from flask import current_app as app
class Download:
#staticmethod
def background_function():
print("testing")
given output:
testing
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
As you can see, the function runs first and prints testing and then runs the application.
Using just the Flask server with Python, the following get request works:
from flask import Flask, request
app = Flask(__name__)
class Result(Resource):
def get(self):
image_id = request.headers.get('image_id')
api.add_resource(Result, '/results')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=int(os.getenv('PORT', 5000)))
However, using Waitress, the following does not work (image_id is None):
from waitress import serve
from flask import Flask, request
app = Flask(__name__)
class Result(Resource):
def get(self):
image_id = request.headers.get('image_id')
api.add_resource(Result, '/results')
if __name__ == '__main__':
serve(app, host="0.0.0.0", port=int(os.getenv('PORT', 5000)))
POST and other GET requests work fine, it's just GET with headers that doesn't work. Anyone have any ideas?
I had the same issue, after searching around I found this issue on GitHub. Apparently it is a security feature and you should not use _ in your header. So you should rename your header to image-id or something else without a _ character for it to work.
all my code is just:
from splinter import Browser
from flask import Flask, request
from splinter.driver.flaskclient import FlaskClient
app = Flask(__name__)
browser = Browser('flask', app=app)
browser.visit('https://www.google.com')
print(browser.html)
which print the 404 html:
404 Not Found
Not Found
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
there is anything I should do?
You are getting a 404 error because your Flask app has no routes.
I believe the purpose of the Splinter Flask client is to test your Flask app, not to test/request other domains. Visiting another domain with the Splinter Flask client will simply request the URL from your domain. You have not specified any routes for your Flask app, so Flask is responding with a 404 error.
Here's an example that shows how the Splinter Flask client is working:
# define simple flask app
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello, World!'
#app.route('/<name>')
def hello_world(name):
return 'Hello, {name}!'.format(name=name)
# initiate splinter flask client
from splinter import Browser
browser = Browser('flask', app=app)
# simple flask app assertions
browser.visit('http://127.0.0.1:5000')
assert browser.html == 'Hello, World!'
browser.visit('http://127.0.0.1:5000/haofly')
assert browser.html == 'Hello, haofly!'
# Notice that requesting other domains act as if it's your domain
# Here it is requesting the previously defined flask routes
browser.visit('http://www.google.com')
assert browser.html == 'Hello, World!'
browser.visit('http://www.google.com/haofly')
assert browser.html == 'Hello, haofly!'
Here's another test that demonstrates what's really going on:
from flask import Flask
app = Flask(__name__)
#app.errorhandler(404)
def page_not_found(e):
return 'Flask 404 error!', 404
from splinter import Browser
browser = Browser('flask', app=app)
browser.visit('http://www.google.com/haofly')
assert browser.html == 'Flask 404 error!'
I call app.run(debug=True) in my flask file.
and I have it deployed with uWSGI and nginx (I followed these instructions)
uwsgi -s /tmp/uwsgi.sock -w flask_file_name:app -H /path/to/virtual/env --chmod-socket 666
But when I get an error, I don't get any debug information in the browser or in the uWSGI log.
Any ideas?
flask_file_name.py:
from flask import Flask, make_response, Response, jsonify
import json
app = Flask(__name__)
app.debug = True
#app.route("/")
def hello():
return "Hello World!"
if __name__ == '__main__':
app.run()
This question is old, but I'll post this for future reference...
If you want to get the werkzeug error page to work with uwsgi, try using werkzeug's DebuggedApplication middleware:
from werkzeug.debug import DebuggedApplication
app.wsgi_app = DebuggedApplication(app.wsgi_app, True)
That should do the trick but DO NOT FORGET to do this ONLY in development environments.
According to the Flask mailing list you cannot use Flask's debug option with uWSGI, because it's not to be used in a forking environment.
You see 502 because flask/werkzeug do not send any data to the webserver,
so nginx will returns a 502.
You can emulate the debugger using --catch-exceptions option in uWSGI
(but please do not do it in production)
So, the reason you're seeing 502s will be because of that. The fix would be to add --catch-exceptions to uWSGI on execution.
The problem is uwsgi does not call app.run(). It calls app(). So instead you can do this:
from flask import Flask
app = Flask(__name__)
app.debug = True
For me it only worked after I combined the two answers above like this:
from flask import Flask
app = Flask(__name__)
from werkzeug.debug import DebuggedApplication
app.wsgi_app = DebuggedApplication(app.wsgi_app, True)
app.debug = True