Serving dynamic files on heroku? - python

I have a flask app that has two threads. One modifies flask templates to keep them up to date from scraped info, and the other is the flask server that takes incoming route requests.
from flask import Flask, render_template
import threading
import RunArbIfDown
app = Flask(__name__, static_url_path='')
#app.route('/')
def index():
return render_template('index.html')
if __name__ == "__main__":
threading.Thread(target=app.run).start()
threading.Thread(target=RunArbIfDown.start).start() # this line continuously updates index.html (every 60s)
When I check the app, index.html is never updated even though there seem to be no errors. Are we allowed to modify files on the heroku dyno? Are there any good solutions for this?

Running threads in a WSGI environment might yield unexpected results. The WSGI server usually manages threads and can create and kill them at any time.
Also you have protected your threading code with a __name__ condition. The code will execute if the file is started directly. A WSGI server will not do that. It will import the file and the the condition will not be met.
A typical way to run recurring tasks in Flask is to use a custom command via cron. It is run as a separate process.

Related

How to invoke/run a Python script using a web URL?

I have a Python script that pulls data from a 3 rd party API. Currently this Pyhton script is automated on server side.
There are few instances where I have to toggle the script manually for new data updates. For the manual toggle I have to login to the server each time and run it from command line. Is there a way where I can create web url or something similar and just run that URL to make that script run from the browser address bar.
One approach you could take is to use Flask, which is a minimal web framework. Here's an example of how you could use it:
from flask import Flask
from your_script import your_func
app = Flask(__name__)
#app.route('/run')
def run_command():
your_func()
return 'Executed your function!'
if __name__ == '__main__':
app.run(debug=False, port=8080)
If you run this code you'd get a web server running on port 8080 that executes your function when you access the url. Here's a tutorial in the Flask documentation to get you started.
I think the easiest way to do this is by using Flask.
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
# your code here
return 'Hello, World!'

Python script with flask server takes too long to exit on Windows

I'm new to Python.
As a part of a project I'm trying to deploy a Flask server locally, through the Windows command line.
My Python version is 3.6.0.
The code:
from flask import Flask
app = Flask(__name__)
#app.route('/') def index():
return '<h1>Hello World!</h1>'
if __name__ == "__main__":
app.run()
The problem:
It's about killing the script as it runs. Launching this script with python deploy.py and hitting CTRL+C shuts it off.
BUT - if I hit access that '/' route via the browser once or more, and a moment later try to kill the script in the same manner, then it would take about 10 seconds of nothing until it responds and is finally killed.
Why is this happening? How can I shut the server off immediately each time for continuous and quick development?
Thanks!!
Well if your goal is continuous and quick development, then you can change flask's configuration.
Best solution for your problem would be setting the DEBUG setting to True. If DEBUG is set to True, then flask will automatically reload the server on code changes.
There are a few ways to do this but the easiest one(because you said you are a beginner) is to pass the debug argument to app.run()
from flask import Flask
app = Flask(__name__)
#app.route('/')
def index():
return '<h1>Hello World!</h1>'
if __name__ == "__main__":
app.run(debug=True)

When is flask's app.before_first_request called when behind apache?

I have some code decorated with #app.before_first_request
In my testing environment when debug is set to true and I run the flask web server by calling python my_flask_server.py the functions decorated with before_first_request do not get called until I actually make a request with the browser.
However when I use Apache and mod_wsgi to serve the flask app, it appears that when I call from my_server import app as application the decorated functions get executed.
This is a problem because my wsgi script looks like this:
import my_server
from my_server import app as application
my_server.configure_stuff() # read from a conf file
application.run(host='0.0.0.0', port=5000, debug=False)
Now I need the configure_stuff() function to execute and to set attributes on the app object. However because #app.before_request decorated functions are run immediately after from my_server import app as application, I get "no attribute errors."
Anyone know how to prevent flask form executing running these decorated functions until a real request has come in?

arduino yun uhttpd flask setup

I'm trying to set up python and flask on the arduino yun. I've managed to run python files via the /etc/config/uhttpd configuration file:
...
list interpreter ".py=/usr/bin/python"
...
The default path for the website's root is: /www in which I've placed a soft link (apps) to the sd card. So now I can run python programs: http://[ip arduino]/apps/helloworld.py
And when I make my first helloflask.py program and run that via python helloflask.py I can see the result at: http://[ip arduino]:5000
But now I want to configure the uhttpd mini webserver (which is capable to exchange information via CGI) to use the flask setup. The URI: http://flask.pocoo.org/docs/deploying/cgi/#server-setup shows some instructions... but I just don't get it. I've made a directory ../apps/uno in which I've placed a __init__.py file with the following content:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "He Flask!"
In the apps dir I've put a file: cgi.py with this content:
from wsgiref.handlers import CGIHandler
from uno import app
CGIHandler().run(app)
Now I when I browse: http://[ip arduino]/cgi.py get a server error occured, contact the administrator (I think this is the CGI interface from uhttpd).
I just don't grasp the CGI configuration for Flask/uhttpd
I looked into this too and got a little further, I was able to setup a simple hello world but once I tried to do something non-trivial I ran into a big issue that uhttpd doesn't support URL rewriting/aliasing. This means your flask app can only be served at the URL of its .py file instead of at a root like http:// (arduino IP) /flaskapp/. None of the routes inside the app will be visible and makes the whole thing unusable.
However, instead of trying to force flask into uhttpd I had great success running the built in server that flask provides. Take a look at this guide I wrote up that uses flask to serve data from a Yun: https://learn.adafruit.com/smart-measuring-cup/overview
The thing to do is add a call to app.run when the script is run, for example make your flask app look like:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello Flask!"
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True, threaded=True)
Then log in to the Yun and run the script using python. Flask's built in server should start serving the app on http:// (arduino IP) :5000/. Make sure to include the host='0.0.0.0' as it's required to listen on the Yun's external network interface. You probably also want debug=True so there are better error messages (and live reloading of the server when the code changes), and I found threaded=True helps because the default server only handles one connection at a time. The Yun is a relatively slow processor so don't expect to service a lot of concurrent requests, however it's quite capable for providing a simple REST API or web application for a few users.
If you want this server to always run on bootup, edit the /etc/rc.local file to include a call to python and your script.

Threaded Flask application not working as expected

I want my flask application to be able to process more than one call at the same time.
I've been testing running with threaded=True or processes=3 with the code below but when I make two calls to the server the later always have to wait for the first one to complete.
I know that it's recommended to deploy the application on a more sophisticated WSGI container but for now I just want my small app to be able to process 2 calls at once.
from flask import Flask, Response, stream_with_context
from time import sleep
app = Flask(__name__)
def text_gen(message):
for c in message:
yield c
sleep(1)
#app.route("/")
def hello():
stream = text_gen('Hello World')
return Response(stream_with_context(stream))
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8080, debug=True, threaded=True)
#Lukas was right.
I was debugging in Google Chrome with two tabs. Apparently Chrome is trying to be smart by using the socket same for both tabs. How Chrome handles that can be changed with the -socket-reuse-policy flag when starting Chrome.
An easier way to test is by using different hostname in each tab or by using curl -N (-N flag for no buffer to see the streaming). Doing that it did indeed work as expected.

Categories