I am writing a home workout program that gives me audio cues for when to switch exercises, which exercises to do, etc... I have this working on my laptop using a small python program to play some short pre-recorded audio files (aiff format) at specified intervals.
However, I'd like to be able to run this program from my iPhone. I attempted to do this by setting up a Flask server on my computer. I can get the program to run via a web browser on the same machine hosting the server, but when I use a different computer or my iPhone, the audio still plays on the host computer's speakers, not the client as desired. The computer hosting the Flask server is running OS X 10.11.6. Here is a basic version of the program:
Flask Python:
app = Flask(__name__)
#app.route('/')
def index():
return render_template('rockrings_stackoverflow.html')
#app.route('/click', methods=['POST'])
def start_workout():
return workout.workout()
if __name__ == '__main__':
app.run(host='0.0.0.0',debug=True)
workout.py:
def workout():
for minute in range(10):
audio_file = homedir + '/audio_files/easy_workout_minute%i.aiff' % minute
print audio_file
os.system('afplay %s' % audio_file)
index.html:
<!DOCTYPE html>
<html>
<body>
<h1>Welcome to the Hangboard Webtool! </h1>
Click the button below to start the easy workout
<br/><br/>
<form action="/click" method="post">
<button type="submit" value="Easy workout">
</form>
</body>
</html>
What is a proper implementation (if there is one) with Flask?
Related
I have a simple flask app that works locally but gets 500'd when testing in IIS.
Edit: I was wrong, initially thought was pandas read issue but the issue is actually coming from subprocess that tries to get the user's IP address:
from flask import Flask, request
import subprocess
app = Flask(__name__)
html = '''
<h1>Test</h1>
<h2>Report Generator</h2>
<p>
<form action="/submitted" method="post">
<label for="reports">Choose a Report:</label>
<select id="reports" name="reports">
<option value="user_test">User Test</option>
</select>
<input type="submit">
</form>
'''
#app.route("/")
def index():
return html
#app.route("/submitted", methods=['POST'])
def show():
select = request.form.get("reports")
if select == 'user_test':
name = 'XXXXXXXX.dcm.com'
result = subprocess.check_output(['nslookup', name])
else:
result = "Not Available"
return result
if __name__ == "__main__":
app.run()
This code runs fine when tested locally. If I remove the part where it runs subprocess to get user IP that works fine on IIS. The trouble is when I try to include the part that runs subprocess.check_output(['nslookup',name]) when running on IIS, which leads to 500 internal server error.
Here is picture of error:
Thanks for the help!
1.You need "import pandas as pd" at top.
2.The error doesn't happen when reading csv, but on the return process.
"df.values" cannot be returned at this situation because "df" is Dataframe type. Instead, you can use:
df = pd.read_csv("uuids.csv")
return df.to_html(header="true", table_id="table")
or
return df.to_csv()
or
return render_template("xxx.html"......)
I have built a web app using flask and I won't be able to host it in a cloud server for the moment. I want to host it in my Windows 10 OS, and I'm not concerned about the app to have secure certificates since it is intended to be shown as prototype. Three files are enough to showcase the result of the app:
myapp.py:
# This a Natural Language Processing app using a machine learning model
class Lingus:
def __init__(self, data):
self.text = data
def output(self):
return self.text+" - "+self.text+"\n"+self.text
Next, is an html file in the folder templates templates/my-form.html:
<form method="POST">
<input name="text">
<input type="submit">
</form>
Finally, a python script using flask for the app called main.py:
from flask import Flask, request, render_template
from myapp import Lingus
app = Flask(__name__)
#app.route('/')
def my_form():
return render_template('my-form.html')
#app.route('/', methods=['POST'])
def my_form_post():
text = request.form['text']
processed_text = text.upper()
result = Ling(text)
return result.output()
if __name__ == "__main__":
app.run(debug=True)
Again, the goal is to make this app accessible through any browser in the web (not locally), using Windows 10. I don't have experience in back-end development or network engineering but I think this is something which is technically possible.
PS: I don't need the app to have security certificates for clients.
v25 Solution in the question's comment worked perfectly. It avoided port forwarding, and it consisted of downloading ngrok and writing one line of code for the app to be hosted locally. You only have to download ngrok on a free account, and write ngrok http < PORT ON WHICH YOUR APP IS RUNNING >. I was running my flask app on the port 5000, so for my case, I did run the app locally, opened ngrok.exe and wrote:
ngrok http 5000
And that's it. Now, I can show my app's prototype to anyone and give it for users to test it. However, the app address changes every 8 hours, you should upgrade your account to get a static address for your app.
After exposure to Svelte/Rollup in the JavaScript world I was impressed that it could refresh the browser automatically when changes were made to the source code. Seeking a similar behaviour in Python I found the package livereload that supports integration with Flask (pretty sure using the same tech). I want the result of the refresh to reflect ALL changes to the source code.
I am using WSL with livereload v2.5.1 and viewing via Chrome. I can successfully get the page to refresh on a detected source code change but the refresh doesn't re-download the new files and just displays the cached files. The page does refresh but I need to hit Ctrl + click refresh to see the actual changes. Using developer mode and turning off caching works as desired. Using Svelte/Rollup doesn't require disabling caching to see source changes.
Most of my changes are to *.css or *.js files served from the 'static' folder in a standard Flask project template and rendered using the 'render_template' function of Flask.
I'm launching my Flask server as follows:
app = create_app()
app.debug = True
app.config['TEMPLATES_AUTO_RELOAD'] = True
server = Server(app.wsgi_app)
server.watch(filepath='static/*', ignore=lambda *_: False)
server.serve(liveport=35729, host='127.0.0.1', port=80)
I would like to not have to disable the cache so that the refresh triggered by livereload actually reflects the changes in the source. Is there a setting in Flask or livereload I can use to achieve this or is this a feature request for the livereload package?
Related Question:
How to automate browser refresh when developing an Flask app with Python?
UPDATE EDIT:
Further testing has shown that this is specifically an issue with Chrome, with Firefox it works as expected out of the box. Digging into the underlying livereload.js library it seems there is a parameter of 'isChromeExtension' which I have tried to force set to True but had no effect.
I came across the same issue and here is what I did to solve the issue.
As you mentioned this is a browser caching problem. So we want invalidate the cached css/js files. We can achieve this by setting a version on the static file. We want the version to change each time you make changes to the css file. What I did feels a bit hacky but you'll get the idea.
Here is what I have for my html template
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Hello World</title>
<link href="{{ url_for('static', filename='main.css', version=time)}}" rel="stylesheet" type="text/css" />
</head>
<body>
<h1 class="hello-color">
{{ message }}
</h1>
</body>
</html>
You can see version=time I am passing the template the current time with the following.
from flask import Flask, render_template
from time import time
app = Flask(__name__)
#app.route("/")
def hello():
return render_template('hello.html', message="Hello World!", time=time())
from time import time and
time=time()
And finally my main python file
from app import app
from livereload import Server
if __name__ == '__main__':
server = Server(app.wsgi_app)
server.serve(port=2200, host='0.0.0.0')
Hopefully this helps you or anyone else running to this issue.
So I asked a few days ago how to run a program from a browser on a different server and someone told me about Flask and I tought I should`ve gave it a try
And that s what I did: I wrote the program
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route('/addnew', methods=['GET', 'POST'])
def send():
if request.method == 'POST':
name = request.form['name']
return render_template('see.html', name=name)
return render_template('index.html')
if __name__ == "__main__":
app.run(host='0.0.0.0')
I made up the most basic form in html so i can at least try the code
<!DOCTYPE html>
<html>
<head>
<title>Pls work</title>
</head>
<body>
<form method="POST" action="/addnew">
First name:<br>
<input type="text" name="name"><br>
</form>
</body>
</html>
I run it from the console (activating venv and all that), but when i go to 'link/addnew' it tells me the page does not exist
In the putty console tells me it runs on 0.0.0.0
I tryed to put the host on 127.0.0.1:5000 but it doesnt also doesnt work
I am really a noobie in this so I try to copy and understand as much as possible, but i dont understand where the problem stands, please help
On Ubuntu use this command to allow traffic to your server on the port 5000:
iptables -I INPUT -p tcp --dport 5000 -j ACCEPT
If that does not work please share your debug logs.
So basically I am trying to build a led project with a raspberry pi zero w. I have gotten the led python scripts working inside my flask web project. But i would like to be able to change the patterns on the led strips just with a button click on the web page that is generated by the pi. Im currently using flask to run the web server and updates send to it. Im also using execnet to run the pattern methods from a python 2 file as the NeoPixel library is only in python 2 and not 3.
from flask import Flask, render_template, request
import execnet
CURRENT_PATTERN = "No Pattern Running"
app = Flask(__name__)
def callPython2(Version, Module, Function, Args):
gw = execnet.makegateway("popen//python=python%s" % Version)
channel = gw.remote_exec("""
from %s import %s as the_function
channel.send(the_function(*channel.receive()))
""" % (Module, Function))
channel.send(Args)
#app.route("/")
def index():
CURRENT_PATTERN = 'BootUp'
callPython2("2.7", "lakeboot", "startUp", "")
templateData = {
'title' : 'LED Pattern Status',
'pattern' : CURRENT_PATTERN,
}
return render_templates("index.html', **templateData)
#app.route("/<patternName>/<action>")
def action(patternName, action):
if action == 'stop':
CURRENT_PATTERN = 'No Pattern Running"
callPython2("2.7", "lakeboot", "turnOff", "")
if patternName == 'TheaterChase':
CURRENT_PATTERN = 'Theater Chase'
callPython2("2.7", "lakeboot", "runTheater", "")
#More Pattern calls like above
templateData = {
'title' : "LED Pattern Status',
'pattern' : CURRENT_PATTERN,
}
return render_template('index.html', **templateData)`
This is what my webPage.py file looks like. The pattern change calls work but then it only does one iteration of the selected pattern, but i would like it to loop until told to stop or a new pattern is selected.
P.S. Sorry if the format is bad Have never posted on here before and also only been working with python for a few months.
EDIT:
Here is the index.html
<!DOCTYPE html>
<head>
<title>LED Status</title>
<link rel="stylesheet" href='../static/style.css'/>
</head>
<body>
<h2> Status </h2>
<h3> Current Pattern ==> {{ pattern }}</h3>
<br>
<h2> Commands </h2>
<h3>
Run Bootup ==>
TURN ON
TURN OFF
</h3>
<h3>
Run Theater Chase ==>
TURN ON
TURN OFF
</h3>
<h3>
Run Pattern Three ==>
TURN ON
</h3>
</body>
</html>
One unusual, but not entirely crazy, approach is to run Flask in a thread, with the main thread controlling the LEDs. The LED side and the Flask side would communicate through a shared data structure, which you should arrange to lock if you're doing anything more complicated than doing an atomic assign to it.
The basic flow is:
Create the share state holder
Inject it into a Flask config
Start the Flask app in a thread
Do your foreground thing (control LEDs in this case) periodically examining the shared state holder for a new setting/command.
Flask handlers interrogate/set via the shared state holder.
For anything more than a single state value, the state holder will want to lock access internally.
I have a working example that controls a camera here.
The key parts, edited down a bit are
def webserver(control):
app.config['CONTROL'] = control
# It isn't safe to use the reloader in a thread
app.run(host='0.0.0.0', debug=True, use_reloader=False)
control = Control()
ui_thread = threading.Thread(target=webserver, args=(control,))
ui_thread.start()
while control.running():
# control the LEDs, periodically interrogating control
From the Flask side,
#app.route('/command', methods=['POST'])
def command():
control = app.config['CONTROL']
control.command(request.form.get('command'))
return redirect('/')