i am a noob in python programming. Recently i was learning Flask framework for web development. After completed some basic flask doc demo i was trying to separate my 1 page simple hello world into mvc.
As in the way this is my project structure
Main folder
---> application [folder]
--> __init__.py
--> route.py
--->run.py
At run.py i have this code :
import application
At the application's _init_.py i have this code :
from flask import Flask
app = Flask(__name__)
import route
And at route.py i have this code :
from flask import Flask
from application import app
#app.route('/')
def index():
return "hello world"
app.run(debug=True,host='0.0.0.0')
Now when a go to my terminal and start server this happens
(venv)nihan#rko:~/apps/blog$ python run.py
* Running on http://0.0.0.0:5000/
* Restarting with reloader
^C^C127.0.0.1 - - [02/Sep/2013 00:25:45] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [02/Sep/2013 00:25:45] "GET / HTTP/1.1" 200 -
Now you can see this script runs correctly but it does not response to and request until i shut the process.
My question is why server does not sends anything until i press CTRL + C ? And how to solve this problem?
You should also avoid circular imports, for example by using blueprints.
run.py
from application import app
app.run(debug=True, host='0.0.0.0')
application/__init__.py
from flask import Flask
from route import mod
app = Flask(__name__)
app.register_blueprint(mod, url_prefix='/')
application/route.py
from flask import Flask, Blueprint
mod = Blueprint('app', __name__)
#mod.route('/')
def index():
return "hello world"
The quick fix of that is
In route.py :
from flask import Flask
from application import app
#app.route('/')
def index():
return "hello world"
app.run(
host='0.0.0.0',
debug=True
)
You should move the app.run() call to run.py. This should happen after everything related to the app is imported, it's not a good idea to have it inside the app itself.
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.
I found and forked the following Flask/SQLAlchemy/Marshmallow example project:
https://github.com/summersab/RestaurantAPI
It works like a charm, and I used it to build a custom API. It runs flawlessly with:
python run.py
Then, I tried to run it on a proper webserver:
uwsgi --http localhost:5000 --wsgi-file run.py --callable app
However, I get 404 for all routes except /, /api, and /api/v1.0. I tried it on Gunicorn with the same results leading me to believe that the problem is with the code, not the webserver config.
All of the following posts have the same problem, but from what I could tell, none of them had solutions that worked for me (I may have missed something):
Flask on nginx + uWSGI returns a 404 error unless the linux directory exists
Unexplainable Flask 404 errors
Nginx+bottle+uwsgi Server returning 404 on every request
Flask application with Blueprints+uWSGI+nginx returning 404's (no routing?)
Flask Blueprint 404
Could someone look at the code in my repo and help me figure out what's wrong?
EDIT:
Per the response from #v25, I changed my run.py to the following:
from flask import Flask, redirect, render_template
from app import api_bp
from model import db, redis_cache
from config import DevelopmentConfig, TestingConfig, BaseConfig, PresentConfig
app = Flask(__name__)
t = 0
def create_app(config_filename):
app.config.from_object(config_filename)
global t
if t == 0:
app.register_blueprint(api_bp, url_prefix='/api/v1.0')
t = 1
if config_filename != TestingConfig:
db.init_app(app)
redis_cache.init_app(app)
return app
#app.route('/')
#app.route('/api/')
#app.route('/api/v1.0/')
def availableApps():
return render_template('availableApp.html')
PresentConfig = BaseConfig
app = create_app(PresentConfig)
if __name__ == "__main__":
app.run(use_debugger=False, use_reloader=False, passthrough_errors=True)
I then ran this with uwsgi, and it works as expected:
uwsgi --http localhost:5000 --wsgi-file run.py --callable app
Thanks for your help!
This could quickly be solved by creating a new file wsgi.py, with the following contents:
import run
PresentConfig = run.BaseConfig
app = run.create_app(PresentConfig)
Then execute with:
uwsgi --http localhost:5000 --wsgi-file wsgi.py --callable app
or...
gunicorn --bind 'localhost:5000' wsgi:app
Why does this work...
If you have a look inside the run.py file, and note what's happening when you launch that directly with python:
if __name__ == "__main__":
PresentConfig = BaseConfig
app = create_app(PresentConfig)
app.run(use_debugger=False, use_reloader=False, passthrough_errors=True)
you can see that app is being created, based on the return value of the create_app function which is passed a config. Note also that the create_app function registers the "other URLs" as part of the api_bp blueprint.
However the code inside this if clause is never executed when the app is executed with uwsgi/gunicorn; instead the app object which is imported is one without the other URLs registered.
By creating the wsgi.py file above, you're doing all of this in a manner which can then be improted by the wsgi/gunicorn executable.
With that in mind, another way to fix this would be to change the last four lines of run.py to look more like:
PresentConfig = BaseConfig
app = create_app(PresentConfig)
if __name__ == "__main__":
app.run(use_debugger=False, use_reloader=False, passthrough_errors=True)
You could then execute this with your original wsgi command.
It's worth noting this may break other code which does from run import app and expects app not to be the return value of create_app (unlikely in this case).
Let me know if you need clarification on anything.
I'm trying to set up a HTTP sever on Google Cloud. I've run this with python and flask with no problems at all. When I go to the cloud console, create the app and deploy, with pure python and flask, an error occurs. Meanwhile, I tried using gunicorn but I get the same type of error.
My main.py file:
from flask import Flask, jsonify
app = Flask(__name__)
#app.route("/")
def hello():
return jsonify({"about": "Hello World"})
if __name__ == '__main__':
app.run(debug=True)
APP.YAML
env: flex
runtime: python
runtime_config:
pythom_version: 3
I expect to receive a string in JSON format like the following:
{
"about": "Hello World"
}
This is a typo: pythom_version, it should be: python_version.
I am running a flask app using celery to offload long running process on a IIS 6.5 server and using python 2.7
The choice of the python 2.7, flask and IIS 7 server are imposed by the Company and cannot be changed.
The flask app works on IIS server (so the server set-up should be correct), except for the following.
I am struggling to find the good implementation to make flask works smoothly on the server.
I searched for similar questions on the site, but none helped so far.
When I am running the flask app on my pc, the application only performs as expected if I use OPTION A or OPTION B.
OPTION A:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello from FastCGI via IIS!"
if __name__ == "__main__":
app.run(threaded=True) # <--- This works
OPTION B:
If I wrap the flask app inside tornado, it works well as well:
from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from myapp import app
http_server = HTTPServer(WSGIContainer(app))
http_server.listen(5000)
IOLoop.instance().start()
OPTION C:
However if I run the flask app only with the default parameters, then it does not work the webserver is not returning the view that should be returned after a task has been offloaded to celery.
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello from FastCGI via IIS!"
if __name__ == "__main__":
app.run() # <--- Default App
Example of view working for OPTION A & B but not for OPTION C or on ISS:
Here below a stripped down example of a async task that is picked by celery. Note that I'm using Flask-Classy to generate the views, so the code is slightly different than the traditional routing in Flask.
class AnalysisView(FlaskView):
### Index page ---------------
def index(self):
return render_template('analysis.intro.html')
### Calculation process ------
def calculate(self, run_id):
t_id = task_create_id(run_id)
current_analysis = a_celery_function.apply_async(args=[x, y], task_id=t_id)
# Redirect to another view --> Not working when OPTION C or on ISS server
return redirect(url_for('AnalysisView:inprogress', run_id=run_id))
### Waiting page ---------------
def inprogress(self, run_id=run_id):
return render_template('analysis.inprogress.html')
My main problem is how can I use OPTION A (preferably, as it involves less change for me) or OPTION B to work together with IIS server?
Is there a way to tell flask to run with threaded=True during the Flask() initialization or via config settings?
Thanks in advance for you help.