Python Multiprocessing running process twice? - python

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.

Related

How do i call two functions in a single route in python flask?

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)

Mongodb seems to load data twice. Not sure why and not sure if I'm loading mongodb right

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.

how do you serialize a python flask variable?

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.

Getting message contiously on telegram

from flask import Flask
from flask import request,jsonify
import requests
import json
app = Flask(__name__)
url = ''
token = ''
def send_message(chat_id,text):
URL = url+token+'sendMessage'
answer = {'chat_id': chat_id, 'text': text}
r = requests.post(URL,json = answer)
return ''
#app.route('/', methods = ['GET','POST'])
def index():
if request.method == 'POST':
r = request.get_json()
chat_id = r['message']['chat']['id']
text = "how are you?"
send_message(chat_id,text)
else:
return "hello world"
if __name__ == '__main__':
app.run()
when I run this after setting the webhook I keep getting the text 'how are you?' continuously. How do i fix this? I saw 2 answers telling to return 200 Ok. Could anyone please help ?

using try except in python but return 400 bad requst from server

I'm tring to upload two files to server
but the try except where I wrote in #app.route('result') is always in exception
from flask import Flask,render_template,redirect, url_for,request,redirect
import os, sys
from pymongo import MongoClient
from werkzeug import secure_filename
app = Flask(__name__,static_folder='static', static_url_path='')
import numpy
#app.route('/')
def showRoot():
return render_template('index.html')
#app.route('/result/')
def result():
return render_template('test.html')
ALLOWED_EXTENSIONS = set(['txt', 'docx', 'png', 'jpg'])
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
#app.route('/request_page/', methods=['GET','POST'])
def request_page():
UPLOAD_FOLDER = '/var/www/helloworldapp/app/uploads/'
UPLOAD_FOLDER = os.path.expanduser(UPLOAD_FOLDER)
if (not os.path.exists(UPLOAD_FOLDER)):
os.makedirs(UPLOAD_FOLDER)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
try:
Case_ID = '171129001'
mRNA_file = request.files['mRNA_file_name']
lncRNA_file = request.files['lncRNA_file_name']
if (mRNA_file != '' and allowed_file(mRNA_file.filename)) and (lncRNA_file != '' and allowed_file(lncRNA_file.filename)):
mRNA_file_name = Case_ID+secure_filename(mRNA_file.filename)
lncRNA_file_name = Case_ID+secure_filename(lncRNA_file.filename)
mRNA_file.save(UPLOAD_FOLDER+ mRNA_file_name)
lncRNA_file.save(UPLOAD_FOLDER + lncRNA_file_name)
#import sys
#sys.path.append('/var/www/helloworldapp/app')
#from . import Expression_profiles_preprocessing
#return(Expression_profiles_preprocessing.Concatenating_gene_expression_profile(Case_ID,mRNA_file_name,lncRNA_file_name))
else:
return 'Upload Failed'
except Exception as e:
return render_template('test.html', error=str(e))
the except result on my website is like this
web result
Is there any solution to solve this problem? By the way , two files that upload by html can be seen in my server's document.
Im going to go out on a limb here without the call stack and say that your issue might be solved by changing this:
mRNA_file = request.files.get('mRNA_file_name')
lncRNA_file = request.files.get('lncRNA_file_name')
Ive run into this issue quite a few times in Flask, and 80% of the time this solved the issue.
Edit:
Your issue is that by default, .get returns None. Therefore, since you are only checking if mRNA_filename or lncRNA_filename does NOT equal an empty string, then this conditional statement is passing. What I would do instead is this:
mRNA_file = request.files.get('mRNA_file_name') <-- Here you can add another argument that would act as the default, else this will return None
lncRNA_file = request.files.get('lncRNA_file_name')
if (mRNA_file and allowed_file(mRNA_file.filename)) and (lncRNA_file and allowed_file(lncRNA_file.filename)):
mRNA_file_name = Case_ID+secure_filename(mRNA_file.filename)
lncRNA_file_name = Case_ID+secure_filename(lncRNA_file.filename)
mRNA_file.save(UPLOAD_FOLDER+ mRNA_file_name)
lncRNA_file.save(UPLOAD_FOLDER + lncRNA_file_name)

Categories