Recursive static content display with Flask - python

G'day,
I've written a piece of software in Python 3.x with PySide which dynamically displays images (as a slideshow) from a network directory. The software works as intended for local machines (i.e. the slideshow is displayed on the machine which is running the software).
I would like to run the software on a centralised server, which then serves each image of the slideshow temporarily on a local network web page. I've managed to serve static content in my code using the Flask library. Below is a snippet of my code:
def ServeImage(self, DisplayImage):
app = Flask(__name__)
#app.route("/")
def main():
return '''<img src='{}' />'''.format(url_for('static', filename=DisplayImage))
app.run(host='10.2.x.x', port=5000)
'DisplayImage' is the output image path from my current code. At present, the above will correctly display the image in the browser at the designated local address. However, I'm unsure how to return to the slideshow component of the software (where the DisplayImage is generated). It appears that once ServeImage() has been called, the code terminates. I believe it's due to the way this example Flask function was put together. What I'm hoping for is detailed in the pseudo-code below:
def ServeImage(self, DisplayImage):
app = Flask(__name__)
'''<img src='{}' />'''.format(url_for('static', filename=DisplayImage))
app.run(host='10.2.x.x', port=5000)
#Timer
self.ImageNumber += 1
self.SlideShow()
I don't know whether this is possible. As mentioned above, it appears that when app.run() is called, that particular address is served forever, so any code coming after app.run() will never be run. What I'd like is: once the image has been served (i.e. once app.run() has been called), the ImageNumber() variable is changed, and the main SlideShow() function is called, which in turn generates the next DisplayImage to be served on the web page.
Any clarification/suggestions here would be great!
Thanks!

Related

how to send data from separate computer to flask app

My use case is I have a flaskapp running
The idea is it'll just display a static page (currently using PySimpleGUI) and upon receiving the information sent from the other computer (such as the name for e.g.) then it'll show the name as a QR code. (so perhaps a constant refresh on the GUI and changing upon receiving the data)
The code setup is this way currently
#app.route('/qrcode', methods=['GET'])
def displayQrCode():
args = request.args
name = args.get('name') #
try:
img = qrcode.make(name)
img.save('checkin-qrcode.png')
# Display QR Code
qrWindowThread = threading.Thread(target=qrCodeWindowShow)
qrWindowThread.start()
print(name)
return 'Success'
except RuntimeError:
return 'Error in GET'
However, being new to Flask i am not sure how to send a string from a separate computer running jupyter notebook to this Flask app. Online tutorials show like having a form field page but i wish to not have an user input.
So for instance if the jupyter notebook code sends a post request to the ipaddress:5000 it should ideally show (correct me here: ipaddress:5000/qrcode?name=JohnDoe)
so the flask app would retrieve this JohnDoe and display it as a QR code. I can hardcode or manually access this page but how would i have it 'listen' to this /qrcode and then Get the value when it's sent. Or am i misunderstanding it all and I need to do it via another way?
EDIT:
Alright third time lucky, I think I understand what you want now. So your use case is a first computer that is displaying a GUI and running a flask server with an route that can take in a string.
There's a second computer that can send a http request to that route with a name and when that happens you want the GUI on the first computer to refresh to display a QR code of the name.
I'd solve this by having the qrcode route write that name to persistent storage. Could be anything sqlite db, an environment variable, a string in a file.
The first computer running the PySimpleGUI interface poles this persistent storage for changes, and if it sees a change then it renders a new QR code for that name and displays it.
There are multiple ways available to do that:
REST API integration
Realtime data transmission using tornado or ??
Through a base origin for data transmission
Hope you get help with this.

How can i run a function based on the status code on a flask app

I have been messing around with flask on my raspberry pi and i've noticed every time i open the webpage i have as a template on it there are a bunch of status codes displayed (mostly 200 thankfully) and i'd like to display them on a seven segment led display.
I have the electronics side of things sorted out and even made a library to control my seven segment display (the main feature being a function that takes an array of 3 digits and displays them). I did all this assuming the easy part would be just inputing the status code but i can't figure out how to do that.
I've looked into it and thought i could use error handling but that would only work for status codes that correspond to an error and not the ones such as 200.
Any pointers ?
You can use #app.after_request
I use this in many of my projects for posting log messages or metrics about calls made to my server. Combining before_request and after_request is also a common solution that many libraries use to implement features such as authentication in the flask framework.
Example:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
print(f"Running from hello_world")
return 'Hello, World!'
#app.after_request
def print_status_code(response):
print(f"Status code is {response.status_code}")
app.run()
After making a GET call to http://127.0.0.1:5000/ You will see:
Running from hello_world
Status code is 200

Is it possible to change code of flask without rerunning the flask server after deployment?

Consider, I have a flask server deployed which routes to multiple webpages. If I want to change content of one route, by changing its code, is it possible to reflect those changes in webpages without rerunning the flask server? It is possible to host and rerun other scripts on the linux server or entriely another flask server as long as the website url(port number and route) doesn't change.
Please suggest any way you can come up with!
setting flask environment will do the thing for you in the shell.
export FLASK_ENV=development
Assuming you are using flask development server,
Yes, its possible using use_reloader=True,
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
# You business logic code
return some_data
if __name__ == '__main__':
app.run(debug=False, host='0.0.0.0', port=8000,
use_reloader=True, threaded=True)
However it is not good idea to use it in production, related Is the server bundled with Flask safe to use in production?
My assumption is that you want your deployment service to recognize that a change has occurred in a file, which prompts it to automatically restart to reflect the changes, rather than you manually restarting the service.
Assuming that you are deploying on a production uWSGI server, starting the service with touch-reload=/path/to/folder would allow uWSGI to reload when the specified file/folder is modified or touched. https://uwsgi-docs.readthedocs.io/en/latest/Options.html#touch-reload
--touch-reload=/path/to/file.txt
I think you can only do this with the Apache Webserver. Refer to the Flask documentation.
I haven't tried it (yet), but when you have deployed your new code any small change in the wsgi-file should automatically reload the code.
You mentioned two requirements
I have a flask server deployed
I would assume you mean it is deployed in a production environment. This automatically rules out debug-mode from the development server, because it is not stable, efficient or secure for production use.
Without rerunning the flask server
This rules out autoreload, because this will completely restart your server. Any requests that come in until the server is ready again will fail.
One way of going about is by running your application with debug mode ON through app.run(debug=True)
The problem with this approach is that your application would be exposed over the internet with the application's internal debugger on which shouldn't be done.
A better way I can think of is to call the functions you need to change frequently from a different file other than where your core flask code exists and change in that file whenever needed. This way you don't need to change your Flask code and you won't need to restart the application
Edit:
A sample Flask route would be
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
# Route's business logic usually goes here
return data
Now, instead of writing your application's business logic in the same file as your route, you could simply write it in a different file as follows and import it in the file with the route:
File with the business logic
def process_hello_world(params):
# Write your business logic here which you want to change without reloading the application
return data
And in the application file with the route call the business logic as follows:
from flask import Flask
from
app = Flask(__name__)
#app.route('/')
def hello_world():
data = process_hello_world()
return data

Catch-all URL with Flask when the path also contains a URL

Ok, so I want to catch all the URLs in my Flask app, with this piece of code
#app.route('/<path:path>')
def catch_all(path):
return path
Just a basic app with shows the relative path of each page. So this works fine for most of the paths (localhost/whatever/I/want for example prints whatever/I/want).
EXCEPT in one case. For example if I type localhost/foo/http://google.com/bar in the URL bar, what I expected to be shown is foo/http://google.com/bar, but what I actually get is only bar. So actually Flask finds the last valid URL and takes the path following this URL.
Is there anyway to catch the real path of our URL?
Edit: I'm running Flask 0.10 using the Google App Engine for Python.
I was able to reproduce your problem with the current Google App Engine SDK; this is caused by the way the bundled CherryPy server parses the request.
The problem applies only to your local dev server, when you deploy the app to Google, a different handler parses the URI and the http:// scheme is left unparsed.
See CherryPy issue #1284 as well as the corresponding appengine devserver ticket.
The work-around is to URI-encode the colon:
http://localhost:8000/foo/http%3A//google.com/bar
works.

web.py loads the page even when the class is renamed

I understand that the browser makes an HTTP request to the bin/app.py application and asks for the / URL, which is commonly the first URL on any website.
Inside bin/app.py I have a list of URLs and what classes they match.
The only ones I have are the '/' and 'index' mappings. It's given in Learn Python the Hard Way that:
This means that whenever someone goes to / with a browser, lpthw.web will find the class index and load it to handle the request.
I have the following code in app.py right now.
import web
urls = ('/','index')
app = web.application(urls,globals())
class whatever:
def GET(self):
a = "Hello World!"
return a
if __name__ == "__main__":
app.run()
In the above code, I named the class "whatever." Even then, when I go to the localhost page, the browser displays "Hello World!"
Why is this happening? Even if I rename one of the urls from "index" to something else, the code works. What am I missing?
By default, the server needs to be restarted after every code change. However, there is a workaround. From the web.py tutorial:
...On the last line add web.reloader so that it reads:
if __name__ == "__main__": web.run(urls, globals(), web.reloader)
This tells web.py to use the web.reloader "middleware" (middleware is a wrapper function to add some functionality to your web server) which reloads your files whenever you edit them, so that you can see the changes in your web browser right away. (For some serious changes, though, you'll still have to restart the server.) You'll probably want to take this out when you make your site public, but it's great while developing

Categories

Resources