from flask import Flask
from flask import render_template, redirect, request
from flask_restful import Resource, Api
import requests
import pickle
app = Flask(name)
api = Api(app)
class HelloWorld(Resource):
def post(self):
r = requests.get('https://samples.openweathermap.org/data/2.5/weather?zip=16802,us&appid=157d320b7d029e653c67902f982784ff')
json_object_r = r.json()
temp_k = float(json_object_r['main']['temp'])
temp_c = temp_k - 273.15
tempp_c = int(temp_c)
pickle_in = open("var.pickle", "wb")
tempp_c = pickle.load(pickle_in)
# pressure
p = requests.get('https://samples.openweathermap.org/data/2.5/weather?zip=16802,us&appid=157d320b7d029e653c67902f982784ff')
json_object_p = p.json()
press_k = float(json_object_p['main']['pressure'])
# wind
# speed
w = requests.get('https://samples.openweathermap.org/data/2.5/weather?zip=16802,us&appid=157d320b7d029e653c67902f982784ff')
json_object_w = w.json()
wind_k = float(json_object_w['wind']['speed'])
# gust
g = requests.get('https://samples.openweathermap.org/data/2.5/weather?zip=16802,us&appid=157d320b7d029e653c67902f982784ff')
json_object_g = g.json()
gust_g = float(json_object_g['wind']['gust'])
return {tempp_c}
api.add_resource(HelloWorld, '/')
if name == 'main':
app.run(debug=True)
Create a program which sends serialised object first:
import flask
import pickle
object_to_send = {1:2}
#app.route('/endpoint')
def endpoint():
return pickle.dumps(object_to_send).hex()
app.run(port=8080)
Then you can call it from another python program and read that object:
import pickle
import requests
object_hex = requests.get('http://127.0.0.1:8080/endpoint').text
object_received = pickle.loads(bytearray.fromhex(object_hex))
print(object_received)
This is definitely not a best practice - perhaps you should serialise as json, if at all possible, or use some framework for messaging, which should support different serialisation methods, or a message bus, like Kafka.
Related
I have a basic flask server with a Generator model loaded. I'm sending an input vector via JSON which is hitting the Generator, which spits out a prediction. This works. I want to then send this image (I would settle for sending it as any kind of data I can reconstruct on the other end) to another application running on the same machine. From what I gather, it might be best to encode the image as base64, but all of my attempts have failed. Any guidance is appreciated.
#app.route("/json", methods=['GET', 'POST', 'PUT'])
def getjsondata():
if request.method=='POST':
print("received POST")
data = request.get_json()
#print(format(data['z']))
jzf = [float(i) for i in data['z']]
jzft = torch.FloatTensor(jzf)
jzftr = jzft.reshape([1, 512])
z = jzftr.cuda()
c = None # class labels (not used in this example)
trunc = 1
img = G(z, c, trunc)
img = (img.permute(0, 2, 3, 1) * 127.5 + 128).clamp(0, 255).to(torch.uint8)
# now what?
I managed a solution. The Python Flask server looks like this and expects to receive a JSON object containing a Z array of 512 floats and truncation of a single float.
from flask import Flask, jsonify, request, send_file # initialize our Flask application
import json
from flask_cors import CORS
import base64
from torchvision import transforms
import dnnlib
import torch
import PIL.Image
from io import BytesIO
from datetime import datetime
import legacy
device = torch.device('cuda')
with dnnlib.util.open_url("snapshot.pkl") as f:
G = legacy.load_network_pkl(f)['G_ema'].to(device) # type: ignore
app = Flask(__name__)
CORS(app)
#app.route("/test", methods=['GET', 'POST', 'PUT'])
def test():
return "OK"
#app.route("/query", methods=['GET', 'POST', 'PUT'])
def getjsondata():
if request.method=='POST':
# print("received POST")
data = request.get_json()
#print(format(data['z']))
jzf = [float(i) for i in data['z']]
jzft = torch.FloatTensor(jzf)
jzftr = jzft.reshape([1, 512])
z = jzftr.cuda()
c = None # class labels (not used in this example)
trunc = data['truncation']
img = G(z, c, trunc)
#img = (img.permute(0, 2, 3, 1) * 127.5 + 128).clamp(0, 255).to(torch.uint8)
img = (img * 127.5 + 128).clamp(0, 255).to(torch.uint8)
# turn into PIL image
pil_img = transforms.ToPILImage()(img[0]).convert("RGB")
#pil_img = PIL.Image.fromarray(img[0].cpu().numpy(), 'RGB')
# SAVING...
#fn = datetime.today().strftime('%Y-%m-%d-%H:%M:%S')
#pil_img.save('saved_images/' + fn + '.jpg')
response = serve_pil_image64(pil_img)
response.headers.add('Access-Control-Allow-Origin', '*')
# response.headers.add('Content-Transfer-Encoding', 'base64')
return response
return 'OK'
def serve_pil_image64(pil_img):
img_io = BytesIO()
pil_img.save(img_io, 'JPEG', quality=70)
img_str = base64.b64encode(img_io.getvalue()).decode("utf-8")
return jsonify({'status': True, 'image': img_str})
if __name__ == '__main__':
app.run(host='localhost', port=9000, debug=True)
As it stands, I am sending said JSON array from a simple JavaScript/HTML site. It then listens for the response, also JSON.
// construct an HTTP request
var xhr = new XMLHttpRequest();
// upon successful completion of request...
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
var json = JSON.parse(xhr.responseText);
// console.log(json);
document.getElementById("image_output").src = "data:image/jpeg;base64," + json.image;
}
}
xhr.open("POST", "http://localhost:9000/json");
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
Running the following Python 3 script and for some reason that I cannot fathom the startWebview function executes twice resulting in two PyWebView windows being opened.
# Import Modules Here
import os
import time
import webview
import os.path
import multiprocessing
from dotenv import load_dotenv
from flask_wtf import FlaskForm
from flask_mde import Mde, MdeField
from wtforms import SubmitField, StringField
from wtforms.validators import InputRequired, DataRequired, Length
from flask import Flask, request, render_template, flash, session, url_for
app = Flask(__name__)
load_dotenv()
mde = Mde(app)
app.config['SECRET_KEY'] = os.environ.get("FLASK_SECRET_KEY")
windowTitle = os.environ.get("WINDOW_TITLE")
fileDirPath = os.environ.get("FILE_DIRECTORY")
def error_flasher(form):
for field, message_list in form.errors.items():
for message in message_list:
flash(form[field].label.text + ': ' + message, 'error')
print(message, message_list)
def fileHandler(form):
savePath = os.path.join(fileDirPath, form.title.data)
f = open(savePath, "w+")
f.write(form.editor.data)
f.close()
def contentLoader(form):
savePath = os.path.join(fileDirPath, form.title.data)
fileName = savePath
f = open(fileName, "r")
return f.read()
class MdeForm(FlaskForm):
title = StringField('Title', validators=[DataRequired()])
editor = MdeField(
validators=[
#InputRequired("Input required"),
Length(min=0, max=30000)
]
)
submit = SubmitField()
#app.route('/', methods=['GET', 'POST'])
def index():
form = MdeForm()
if form.validate_on_submit() and form.editor.data == "":
form.editor.data = contentLoader(form)
elif form.validate_on_submit() and form.editor.data != "":
session['editor'] = request.form['editor']
fileHandler(form)
form.title.data = ""
form.editor.data = ""
return render_template("index.html", form=form, windowTitle=windowTitle)
def startFlaskServer():
app.run(debug=True)
def startWebview():
webview.create_window(windowTitle, 'http://localhost:5000')
webview.start(debug=True)
if __name__ == "__main__":
p1 = multiprocessing.Process(target=startFlaskServer)
p2 = multiprocessing.Process(target=startWebview)
p1.start()
time.sleep(2)
p2.start()
p2.join()
p1.terminate()
As seen in the above image it would appear that the cause is two GET requests as the second Webview only loads after the second GET request.
Thanks in advance!
It would appear that this issue is caused by Multiprocessing re-evaluating the file as suggested by #Carcigenicate.
Problem solved by moving from Multithreading to threading.
I am currently trying to convert this code:
https://github.com/marionacaros/elisabot
which is a telegram bot code to python flask
I am using this code:
https://github.com/huzaifsayed/coronabot-chatterbot
as the skeleton code.
My app.py looks like this:
from flask import Flask, render_template, request, session
from PIL import Image
from caption import get_question
import requests
from functools import partial
import logging
import random
from evaluate_chatbot import load_chatbot_model, give_feedback
import string
import os
import json
questions = ''
num_images = 7
model_dir = ''
img_directory = 'data/my_test_images/'
test_data_file = 'data/filenames_list/my_test_filenames.txt'
idx = 0
img_path = ''
shown_img_paths = []
def get_random_pic():
count = 0
global shown_img_paths
with open(test_data_file) as f:
lines = f.readlines()
img_path = random.choice(lines)
while img_path in shown_img_paths:
img_path = random.choice(lines)
count += 1
if count == 30:
return ''
if img_path not in shown_img_paths:
shown_img_paths.append(img_path)
print('image path ', img_path)
return img_directory + img_path.rstrip()
def feedback_and_question_2(reply):
out = give_feedback(encoder, decoder, searcher, voc, reply)
out = "".join([" " + i if not i.startswith("'") and i not in string.punctuation else i for i in out]).strip()
out = out.split('.', 1)[0]
if '?' in out:
out = out.split('?', 1)[0] + '?'
if out == 'what?':
out = 'Nice'
if out == 'no':
out = 'ok'
return(out)
def VQG(response):
img_path = get_random_pic()
image = Image.open(img_path)
image.show()
questions = get_question(img_path)
return questions
# Load Model
checkpoint_iter = 13000
load_model = os.path.join('checkpoints_dialog_model/cornell_model/cornell-movie-dialogs/fine_tunned_cornell', '{}_checkpoint.tar'.format(checkpoint_iter))
encoder, decoder, searcher, voc = load_chatbot_model(load_model)
print("Bot started")
### Routes here ###
app = Flask(__name__)
app.static_folder = 'static'
# Config logging
log_format = '%(levelname)-8s %(message)s'
logfile = os.path.join(model_dir, 'eval.log')
logging.basicConfig(filename= logfile, level=logging.INFO, format=log_format)
logging.getLogger().addHandler(logging.StreamHandler())
#app.route("/")
def home():
return render_template("index.html")
#app.route("/get")
def get_bot_response():
response = request.args.get('msg')
logging.info(response)
return str(VQG(response))
# #app.route("/get")
# def chatbot():
# response = request.args.get('msg')
# logging.info(response)
# out = feedback_and_question_2(response)
# return out
So basically i can only call one function is the app.route("/get"), and i need to call 2 functions concurrently without exiting the function
You can use the concurrent API to launch two threads in parallel and gather their results syncronously.
import concurrent.futures
from flask import jsonify
#app.route("/get")
def get_bot_response():
response = request.args.get('msg')
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as ex:
f1 = ex.submit(VQG, response)
f2 = ex.submit(feedback_and_question_2, response)
# Wait for results
r1 = f1.result()
r2 = f2.result()
return jsonify(ans1=str(r1), ans2=r2)
I'm trying to get my flask app to load a csv file into mongodb and then display the data back. For some reason, somewhere within my app the app the data gets duplicated. Don't really know how to debug it and not sure if I'm setting up the data load in the right place in the first place. Any advice would be appreciated. Relevant code is below:
from flask import Flask, render_template, request, redirect
import pymongo
from pymongo import MongoClient
import io
import csv
import json
import ast
app = Flask(__name__)
client = MongoClient("mongodb://db:27017")
db = client.projectDB
"""
HELPER FUNCTIONS
"""
def loadDB():
print("Initializing mongodb client")
db_collection = db['recipe_data']
#Uniqueness constraint for name, not necessary?
# db_collection.createIndex( { "name": 1 }, { unique: true } )
if db_collection.count() == 0:
recipes = db_collection.recipes
loaded_recipes_list = loadRecipes()
for recipe in loaded_recipes_list:
recipes.insert_one(recipe)
print("Database loaded successfully!")
def loadRecipes():
recipe_data = []
#Load recipes
csv_file = "./recipes_short.csv"
rows = io.open(csv_file, "r", encoding="utf-8")
reader = csv.reader(rows)
for data in reader:
recipe = {}
recipe['name'] = data[0]
recipe['id'] = data[1]
recipe['minutes'] = data[2]
recipe['contributor_id'] = data[3]
recipe['submitted'] = data[4]
recipe['tags'] = data[5].lstrip('[').rstrip(']').replace("'", "").split(',')
recipe['n_steps'] = data[6].lstrip('[').rstrip(']').replace("'", "").split(',')
recipe['steps'] = data[7]
recipe['description'] = data[8].lstrip('[').rstrip(']').replace("'", "").split(',')
recipe['ingredients'] = data[9]
recipe['n_ingredients'] = data[10].lstrip('[').rstrip(']').replace("'", "").split(',')
recipe_data.append(recipe)
print(recipe_data)
return recipe_data
#app.route("/")
def home():
return render_template('index.html')
if __name__ == '__main__':
loadDB()
app.run(debug=True,host='0.0.0.0')
It's because you are running flask with debug=True. This will reload the file when starting and therefore will run your data loader twice.
If you take the flag off (which you should do in production anyway), it will not reload.
I've been working on trying to edit a webhook that was originally meant to be used for a weather API to get to be used with a postcode/zipcode API. The original file is here: https://github.com/dialogflow/fulfillment-webhook-weather-python/blob/master/app.py
I can't understand where mine is different, I thought I had solved it when I replaced urlencode with quote but alas, it wasn't enough.
The problem is very unlikely to do with the source json request that collects the postcode in postcodeValue(). The api url comes out correct when you enter it into a browser and is presented quite simply.
https://api.getaddress.io/find/SW11%201th?api-key=I98umgPiu02GEMmHdmfg3w12959
Is it in the correct format? Maybe I need to convert it to become even more JSON then it already is. This question is essentially an end of day brain dump that I I'm hoping that someone can save me with.
from __future__ import print_function
from future.standard_library import install_aliases
install_aliases()
from urllib.parse import urlparse, urlencode, quote
from urllib.request import urlopen, Request
from urllib.error import HTTPError
import json
import os
from flask import Flask
from flask import request
from flask import make_response
# Flask app should start in global layout
app = Flask(__name__)
#this line is just naming conventions I reckon with a reference to expect to receive data as POST
#app.route('/webhook', methods=['POST'])
def webhook():
req = request.get_json(silent=True, force=True)
#who knows where this is getting printed
print("Request:")
print(json.dumps(req, indent=4))
res = processRequest(req)
res = json.dumps(res, indent=4)
# print(res)
r = make_response(res)
r.headers['Content-Type'] = 'application/json'
return r
def processRequest(req):
if req.get("result").get("action") != "yahooWeatherForecast":
return {}
baseurl = "https://api.getaddress.io/find/"
apikey = "?api-key=I98umgPiu02GEMmHdmfg3w12959"
yql_query = postcodeValue(req)
if yql_query is None:
return {}
#this line is the actual api request
yql_url = baseurl + quote(yql_query) + apikey
result = urlopen(yql_url).read()
data = json.loads(result)
res = makeWebhookResult(data)
return res
#this function extracts an individual parameter and turns it into a string
def postcodeValue(req):
result = req.get("result")
parameters = result.get("parameters")
postcode = parameters.get("postcode")
if postcode is None:
return None
return postcode
#def housenoValue(req):
# result = req.get("result")
#parameters = result.get("parameters")
#houseno = parameters.get("houseno")
#if houseno is None:
# return None
#return houseno
def makeWebhookResult(data):
longitude = data.get("longitude")
if longitude is None:
return {}
#def makeWebhookResult(data):
# query = data.get('query')
# if query is None:
# return {}
# result = query.get('results')
# if result is None:
# return {}
# channel = result.get('channel')
# if channel is None:
# return {}
# item = channel.get('item')
# location = channel.get('location')
# units = channel.get('units')
# if (location is None) or (item is None) or (units is None):
# return {}
# condition = item.get('condition')
# if condition is None:
# return {}
# print(json.dumps(item, indent=4))
speech = "Sausage face " + longitude
print("Response:")
print(speech)
return {
"speech": speech,
"displayText": speech,
# "data": data,
# "contextOut": [],
"source": "apiai-weather-webhook-sample"
}
#More flask specific stuff
if __name__ == '__main__':
port = int(os.getenv('PORT', 5000))
print("Starting app on port %d" % port)
app.run(debug=False, port=port, host='0.0.0.0')
Here is a bit cleaner version of your code:
from urllib.request import urlopen
import os
from flask import Flask
app = Flask(__name__)
#app.route('/webhook', methods=['GET'])
def webhook():
res = processRequest()
return res
def processRequest():
try:
result = urlopen("https://api.getaddress.io/find/SW11%201th?api-key=I98umgPiu02GEMmHdmfg3w12959").read()
return result
except:
return "Error fetching data"
if __name__ == '__main__':
port = int(os.getenv('PORT', 5000))
print("Starting app on port %d" % port)
app.run(debug=False, port=port, host='0.0.0.0')
Open your browser and go to http://localhost:5000/webhook and you should see a response.