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.
Related
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.
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!'
I tried to find a solution for my problem in other questions but I couldn't.
I downloaded the python flask and made my first flask app and it ran fine.
Here is the code:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def index():
return "Hello, world!"
When I ran my second file where I had added an app.route ("/ david") and followed the same procedure again, refreshed it and nothing changed.
That is to say, I was going to / david and I get an URL error
Here is my second file
from flask import Flask
app = Flask(__name__)
#app.route("/")
def index():
return "Hello, world!"
#app.route("/david")
def david():
return "Hello, David!"
I tried the same with other files which have some added routes and the result is the same as the first file
Thanks for your answers, I hope to solve my problem.
You did not run the app. What you did is just create a structure for flask, but did not start the server.
Just add:
app.run()
To the bottom of the file and it will work. It will with start the flask server at http://localhost:5000.
By default, flask runs on port 5000.
It can be changed by:
app.run(host="0.0.0.0", port=xxxx)
0.0.0.0 means it accepts request from anywhere on the port specified.
Make sure you have all the permissions and nothing else is running if you want it to run on port 80.
Hope this helps. Good luck.
I had the same issue. Try first by restarting your IDE; this worked for me. If that doesn't work, try clearing your ports for Windows:
Open Task manager
Click on the “Processe” tab
Enable the "PID" column: View -> Select Columns -> Check the box for PID
Find the PID (in your case, 5000 - flask default port) and click “END PROCESS"
WHAT WORKS
I created a simple Web Application in Flask that takes care of operating a simple return render_template("index.html") when the root node is accessed by a Web Browser.
# app.py
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/")
def show_index():
return render_template("index.html")
if __name__ == "__main__":
app.run(port=80)
The index.html is a simple page that uses tracking.js in order to get the user webcam and track his/her face in the live video stream.
Opening cmd and typing python app.py results in Running on http://127.0.0.1:80/
Accessing the above mentioned URL results in the correct display of the page, that asks me for permission to use the camera, opens it and correctly tracks my face in the live video feed. So it's all working fine till here.
WHAT DOES NOT WORKS
The problem I'm experiencing arises when I dockerize my application using Docker. docker-machine ip is 192.168.99.100
Opening cmd and typing: docker run -p 4000:80 my_face_track_app results in: Running on http://0.0.0.0:80/
Accessing 192.168.99.100:4000 results in the correct display of index.html but I am not asked anymore for permission on the camera and inspecting the JS console I read the following exception:
getUserMedia() no longer works on insecure origins
Here the full error log:
I know the error is telling me I'm not serving the page in HTTPS.
Has anyone else encountered this problem?
What would be the proper solution to the issue or a possible walkaround?
Any help will be highly appreciated, thank you a lot in advance
WHAT I HAVE TRIED TO DO IN ORDER TO SOLVE THE PROBLEM
Since an HTTPS serving of the page is needed in order for JS to execute the function getUserMedia() I tought about serving my Flask application with an SSL certificate by modifying app.py like this:
# app.py
from flask import Flask, render_template
import OpenSSL
app = Flask(__name__)
#app.route("/")
def show_index():
return render_template("index.html")
if __name__ == "__main__":
app.run(port=80, ssl_context="adhoc")
I then dockerized the app building a new image. Typing:
docker run -p 443:80 facetrackapphttps
Results in
Running on https://127.0.0.1:80
So yeah, here HTTPS is ON: the problem is that the port 80 of the HTTPS Flask App is mapped to the port 443 of the docker-machine ip 192.168.99.100.
Trying to access 192.168.99.100:443 does not work and nothing is shown.
Does anybody have an idea about how to do this?
If your application is bound to 127.0.0.1 inside the container, you're not going to be able to access it from your host. According to the flask docs, flask will bind to 127.0.0.1 by default.
You'll need to modify your service so that it binds to 0.0.0.0 inside the container:
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80, ssl_context="adhoc")
I copy pasted the flask's 'hello world' app from their website and am trying to run it. I get an error message in Chrome saying
Internal Server Error
The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
Here is the 'hello world' app straight from flasks website
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.debug = True
app.run()
What I have tried:
-temporarily disabling Avast!
-disabling windows firewall
-ensuring that the flask module is installed
This was working a couple days ago actually...
I don't know why but when I change
app.run()
to
app.run(port=4996)
it starts working. No idea why the default port is throwing an error. Oh well.
from flask import Flask
app = Flask(__name__)
#app.route('/')
def index():
return 'Hello World'
if __name__ == '__name__':
app.run()
app.run(port=5000)
For Windows machines you can use the command in cmd:
set FLASK_APP=python_file.py
flask run
Some other process is running on port 5000. It may be you still have an old Flask process running, with broken code. Or a different web server altogether is running on that port. Shut down that process, or run on a different port.
You can switch to using a different port with the port argument to app.run():
app.run(port=8080)
If you can't figure out what process is still bound to port 5000, use the Windows Resource Monitor or run netstat -a -b from a command line. See How can you find out which process is listening on a port on Windows?
I think you are trying to copy the route generated through your flask program in cmd by pressing ctrl+c which quits your running flask program . i was also doing the same.just try to type the route generated by your flask program on your browser . it will definitely resolve your problem.
Where your python file store is, use cmd and then go on your file store directory, then
set FLASK_APP=filename.py
After this your flask run cmd will work.
from flask import Flask
app = Flask(__name__) # creating app
#app.route('/', methods['GET']) #routing it to the home page
def home(): #function
return "hello world"
app.run(port=5000, debug=true) #function call by the app
Add port and use methods whatever your need is USE GET in your case and try to remove your cache and run the this code it will definitely work.