making a function that run after certain condition in python flask - python

I want to build a Line chatbot that when a POST requests is received and will parse the receive POST requests information to the chatbot users.
import os
import sys
from argparse import ArgumentParser
import json
from flask import Flask, request, abort,Response,jsonify
import requests
from linebot import (
LineBotApi, WebhookHandler
)
from linebot.exceptions import (
InvalidSignatureError, LineBotApiError
)
from linebot.models import (
MessageEvent, TextMessage, TextSendMessage,SourceUser
)
app = Flask(__name__)
data=''
#app.route('/data', methods=['POST'])
def get_data():
"""devicename,exceptionType,temperature,mask,stranger"""
device_name = request.form.get('device_name')
exceptionType = request.form.get('exceptionType')
temperature = request.form.get('temperature')
mask = request.form.get('mask')
stranger = request.form.get('stranger')
global data
data=f"device_name = {device_name} exceptionType = {exceptionType} temperature = {temperature} mask = {mask} stranger = {stranger}"
return_status = {"success":"true"}
return jsonify(return_status)
while len(data) > 1:
try:
line_bot_api.broadcast(
messages=TextSendMessage(text=str(data))
)
data=''
except LineBotApiError as e:
raise e
if __name__ == "__main__":
arg_parser = ArgumentParser(
usage='Usage: python ' + __file__ + ' [--port <port>] [--help]'
)
arg_parser.add_argument('-p', '--port', default=8000, help='port')
arg_parser.add_argument('-d', '--debug', default=False, help='debug')
options = arg_parser.parse_args()
app.run(debug=options.debug, port=options.port)
here I have two parts, first is the POST requests receiver. and second is the part that checks the condition if data is present. But when I send the POST requests, the line_bot_api.broadcast does not send the message to the chatbot user. I only saw examples of flask code that has a #app.route() so I was wondering if something like this works? or is there a better way to implement the condition (instead of checking data value, is it better to check if function get_data() ran or requests has been sent to our /data route)

The while loop stops immediately because the condition fails. One way to get around this and do what you want is by using threads.
import os
import sys
from argparse import ArgumentParser
import json
import threading
from flask import Flask, request, abort,Response,jsonify
import requests
from linebot import (
LineBotApi, WebhookHandler
)
from linebot.exceptions import (
InvalidSignatureError, LineBotApiError
)
from linebot.models import (
MessageEvent, TextMessage, TextSendMessage,SourceUser
)
app = Flask(__name__)
data=''
#app.route('/data', methods=['POST'])
def get_data():
"""devicename,exceptionType,temperature,mask,stranger"""
device_name = request.form.get('device_name')
exceptionType = request.form.get('exceptionType')
temperature = request.form.get('temperature')
mask = request.form.get('mask')
stranger = request.form.get('stranger')
global data
data=f"device_name = {device_name} exceptionType = {exceptionType} temperature = {temperature} mask = {mask} stranger = {stranger}"
return_status = {"success":"true"}
return jsonify(return_status)
def broadcast():
while True:
if len(data) < 1 : continue
try:
line_bot_api.broadcast(
messages=TextSendMessage(text=str(data))
)
data=''
except LineBotApiError as e:
raise e
if __name__ == "__main__":
arg_parser = ArgumentParser(
usage='Usage: python ' + __file__ + ' [--port <port>] [--help]'
)
arg_parser.add_argument('-p', '--port', default=8000, help='port')
arg_parser.add_argument('-d', '--debug', default=False, help='debug')
options = arg_parser.parse_args()
broadcast_thread = threading.Thread(target=broadcast)
broadcast_thread.start()
app.run(debug=options.debug, port=options.port)
This is definitely not the best way. But it works.

Related

python flask app in docker is not refreshing images in frontend

I am running a python flask app on Docker. The app consists of a frontend in which a user provides a search term and the app returns an HTML file with insights and images. The problem is that after the first time I try the app, the HTML file keeps returning the images of the first try.
If I erase cookies, the problem is solved. But I cannot ask a user to erase cookies every time she needs to use the app.
I tried using os.remove before saving every image, but this doesn't work.
from googleapiclient.discovery import build
import pandas as pd
import matplotlib.pyplot as plt
from flask_restful import Api
from flask import Flask,render_template,request
import math
application = Flask(__name__)
api = Api(application)
#application.route('/')
def home():
return render_template('home.html')
#application .route('/predict',methods=['POST'])
def predict():
term1 = request.form['term1']
my_results_list = []
def google_query(query, api_key, cse_id, **kwargs):
query_service = build("customsearch", "v1", developerKey=api_key)
query_results = query_service.cse().list(q=query, cx=cse_id, **kwargs).execute()
return query_results['items']
my_results = google_query(term1,'api_key','cse_id', num = 10)
for result in my_results:
my_results_list.append(result['link'])
data = pd.DataFrame(my_results_list)
values = [1] * len(data)
N = len(values)
values += values[:1]
angles = [n/float(N)*2*math.pi for n in range(N)]
angles += angles[:1]
plt.polar(angles,values, marker='.', color = 'red')
temp = 'graph'
temp = 'static/' + temp + '.png'
plt.savefig(temp)
html = []
html.append("""<!DOCTYPE html><html>""")
html.append("""<img src="{{url_for('static',filename='graph.png')}}"/>""")
html = ' '.join(html)
temp = 'templates/result_vf.html'
print(html, file = open(temp,'w',encoding='utf-8'))
return render_template('result_vf.html')
if __name__ == '__main__':
application.run(host=('0.0.0.0'), port=8080 ,debug=True)

Flask - inheritance - python's self issue

I have a little flask application, it is mostly written with methods (just one class).
Can someone explain me - example would be great - why I am receiving 1 missing argument after adding self to method declaration?
Here is a code:
from __future__ import print_function
from flask import Flask, render_template, make_response
from flask import redirect, request, jsonify, url_for
from multiprocessing import Value
from flask_classful import FlaskView
#from settings import *
from utils.settings import *
import logging
import linecache
import os
import simplejson as json
import mysql.connector
counter = Value('i', 0)
app = Flask(__name__)
class FlaskCLS(FlaskView):
app.debug = False
app._static_folder = os.path.abspath("templates/static/")
#app.route('/v1/api/cords', methods=['GET', 'POST', 'OPTIONS'])
def snd_post():
res = make_response({'x': '55.333', 'y': '18.666'})
return res
#app.route('/', methods=['GET', 'POST', 'OPTIONS'])
def index():
result = []
data = request.data
with counter.get_lock():
counter.value += 1
out = counter.value
with open(str(out), 'a') as dumping:
json.dump(data, dumping)
# ----------------------parser-section------------
with open(str(out), 'r+') as file:
content = file.readlines()
for line in content:
result.append(line.replace('\\', "").replace('"', "").
replace('{', "").replace('}', '').
replace(']', '').replace(',','\n').
replace('[',''))
f = open(str(out), 'w')
f.write('')
f.close()
with open(str(out), 'a') as appending:
appending.write('')
for line in result:
appending.write(line)
# --------------------cords-grabbing-------------
x = linecache.getline(str(out), 1)
y = linecache.getline(str(out), 2)
fx = open('x', 'w')
fy = open('y', 'w')
fx.write(x)
fx.close()
fy.write(y)
fy.close()
mydb = mysql.connector.connect(
host=db_host,
user='root',
auth_plugin='mysql_native_password',
password=password,
buffered=buffered,
database=database)
mycursor = mydb.cursor()
mycursor.execute('select nazwa, x, y, SQRT(POW(69.1 * (x - 54.111), 2) + POW(69.1 *(18.222 - y)\
* COS(x / 57.3), 2)) as distance from wet_dane having distance <125 order by distance;')
mycursor.fetchall()
mydb.commit()
# ---------------------empty-files----------------
str_directory = '/var/www/html/'
list_files = [x for x in os.listdir(str_directory) if x[0] != '.']
for each_file in list_files:
file_path = '%s/%s' % (str_directory, each_file)
if os.path.getsize(file_path) == 0:
os.remove(file_path)
else:
pass
return render_template('layouts/index.html')
flask = FlaskCLS()
# ---------------------runner-section-------------
if __name__ == '__main__':
log = logging.getLogger('werkzeug')
log.disabled = True
app.run(host, port, debug, ssl_context=context)
My point is - how properly add self to index and snd_post methods?
I want to pass - for example - x variable from index to snd_post in the same class.
Without self flask doesn't allow me to do such an operation.
Thanks.
I don't have experience with Flask-Classful, but it looks that you are supposed to register the routes to the app this way:
class QuotesView(FlaskView):
def index(self):
return "Hello"
QuotesView.register(app)
Instead of the #app.route(...) decorator.
Ok, i've made a solution for this, now my main python file looks like this:
from __future__ import print_function
from flask import Flask, render_template, make_response
from multiprocessing import Value
from utils.settings import *
from py_methods.post import Post
from py_methods.db_connect import Db_conn
from py_methods.empty_files_del import DeleteEmpty
from py_methods.files_operations import Files
import logging
import os
app = Flask(__name__)
app.debug = False
app._static_folder = os.path.abspath("templates/static/")
#app.route('/v1/api/cords', methods=['GET', 'POST', 'OPTIONS'])
def snd_post():
return Post.snd_post()
class Main():
#app.route('/', methods=['GET', 'POST', 'OPTIONS'])
def index():
Files.parsing()
DeleteEmpty.del_empty()
Db_conn.wet_db()
return render_template('layouts/index.html')
# ---------------------runner-section-------------
if __name__ == '__main__':
log = logging.getLogger('werkzeug')
log.disabled = True
app.run(host, port, debug, ssl_context=context)
So it's just a runner - every method I wrote has own file and own class. This allow me to inheritance the variables. We can close this topic. Thansk for the answers.

Python-Flask - render template within a class gives 404

I am trying to run python with html using flask locally, i try to render a template within a class object, it compiles but when i try to access it on http://localhost:5000 it gives me 404. Could anyone tell what I'm doing wrong here?
I am trying to display values from a json format using chart.js library.
from flask import Flask
from flask import render_template
import os.path
import json
app = Flask(__name__)
#import the json file
_player_json_file = os.path.join(os.path.dirname(__file__), 'players.json')
def read_players(player_file=None):
if player_file is None:
player_file = _player_json_file
try:
data = json.loads(open(player_file).read())
except IOError:
return {}
#make player dictionary
players = {}
#get player ID from json file = data.
for playerID in data:
players[playerID] = Player_data(data[playerID])
return players
class Players_Data (object):
#app.route("/")
def __init__(self, data):
"""
Assign all the values from the json file to new variables
the values are birth date age weight...
"""
self.player_ID = data['gsis_id']
self.gsis_name = data.get('gsis_name', '')
self.player_fullname = data.get('full_name', '')
self.player_first_name = data.get('first_name', '')
self.player_last_name = data.get('last_name', '')
self.player_weight = data.get('weight','')
self.player_height = data.get('height' , '')
self.player_birth = data.get('birthdate', '')
self.player_pro_years = data.get('years_pro', '')
self.player_team = data.get('data', '')
values = [player_ID,gsis_name,player_fullname,player_first_name,player_last_name,player_weight]
return render_template('chart.html', data=data, values=values)
if __name__ == "__main__":
app.run(host='localhost')
I don't think template rendering is the issue here. You can just return a string from your view as an example.
You get a 404 because that's not how you do classy views in flask. You can have a look here: http://flask.pocoo.org/docs/0.12/views/
But essentially you have to extend from flask.views.View and then manually attach your route to app instance, so it looks something like this:
from flask import Flask
from flask.views import View
app = Flask(__name__)
class Players_Data(View):
def dispatch_request(self):
return 'LOL'
app.add_url_rule('/', view_func=Players_Data.as_view('show_users'))
if __name__ == "__main__":
app.run(host='localhost')

Attempt to use invalid handle -1 in Kodi

I am learning Python through the development of a Kodi add-on. I am trying to display an image using the xbmcplugin.setResolvedUrl() function but I get an error:
'Attempt to use invalid handle -1' error.
I am get rid of the error when including li.setProperty("IsPlayable", "true") in my addFile function but then the image is not displayed.
What am I doing wrong?
My code:
import sys
import urllib
import urlparse
import xbmcgui
import xbmcplugin
import xbmcaddon
my_addon = xbmcaddon.Addon()
addon_path = xbmc.translatePath(my_addon.getAddonInfo('path'))
base_url = sys.argv[0]
addon_handle = int(sys.argv[1])
args = urlparse.parse_qs(sys.argv[2][1:])
mode = args.get('mode', None)
def build_url(query):
return base_url + '?' + urllib.urlencode(query)
def addFile(filename, filepath):
filedir = build_url({'mode': 'display', 'filepath': filepath})
li = xbmcgui.ListItem(filename)
xbmcplugin.addDirectoryItem(handle=addon_handle, url=filedir, listitem=li)
def displayImage(url):
li = xbmcgui.ListItem('Sample image')
li.setPath(url)
xbmcplugin.setResolvedUrl(addon_handle, True, listitem=li)
xbmc.log('Display image...',level=xbmc.LOGNOTICE)
if mode is None:
fileurl = 'https://elmicrolector.files.wordpress.com/2016/10/breu-14-a1.jpg'
addFile('Sample image', fileurl)
xbmcplugin.setContent(addon_handle, 'files')
xbmcplugin.endOfDirectory(addon_handle)
elif mode[0] == 'display':
displayImage(args['filepath'][0])
I found out the xbmcplugin.setResolvedUrl() function can only be used with videos, not with images.

Pass variables between different scripts python

I made a script python app.py and I managed to store data from a javascript form, thanks to a flask app :
app = Flask(__name__)
app.config.from_object('config')
db.init_app(app)
#app.route('/getFormData', methods=['POST'])
def get_javascript_data():
params = request.form.to_dict()
sunElevation = params['sunElevation']
cloudCoverage = params['cloudCoverage']
thresholdNDVI = params['thresholdNDVI']
limitScene = params['limitScene']
city = params['city']
data_search = passData(sunElevation, cloudCoverage, thresholdNDVI, limitScene, city)
return jsonify(data_search.data_dict)
if __name__ == '__main__':
app.run()
Here is the definition of the class passData, in models.py :
class passData:
def __init__(self, sunElevation, cloudCoverage, thresholdNDVI, limitScene, city):
self.sunElevation = sunElevation
self.cloudCoverage = cloudCoverage
self.thresholdNDVI = thresholdNDVI
self.limitScene = limitScene
self.city = city
self.data_dict = [{'sunElevation':self.sunElevation,'cloudCoverage':self.cloudCoverage, 'thresholdNDVI':self.thresholdNDVI, 'limit':self.limitScene, 'city':self.city}]
I need to use those different parameters (sunElevation...) in an other script, in a other folder, to execute a search of imagery and then run the script associated. My problem is that I don't know how to pass those data, because they seem to only exist in the fonction defined in the get_javascript_data().
If someone has an idea that could help me !
You just have to import the other script, call the function and pass the parameters:
app = Flask(__name__)
app.config.from_object('config')
db.init_app(app)
from path.to.your.file import your_function
#app.route('/getFormData', methods=['POST'])
def get_javascript_data():
params = request.form.to_dict()
sunElevation = params['sunElevation']
cloudCoverage = params['cloudCoverage']
thresholdNDVI = params['thresholdNDVI']
limitScene = params['limitScene']
city = params['city']
data_search = passData(sunElevation, cloudCoverage, thresholdNDVI, limitScene, city)
# call the function and pass the parameters
your_function(sunElevation, cloudCoverage) #...
return jsonify(data_search.data_dict)
Try adding the following code in your file, then import the script
import os, sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')))
from eosLandviewer.main_naturalite import search

Categories

Resources