Run c++ executable from python flask - python

I am trying to run a c++ executable from a flask application.
I created two input for the arguments and one button to submit and run the executable.
What I want to execute is this command line: ./Ex02_DriveStatus 5 blablabla.sw
The executable Ex02_DriveStatus is on the same folder than the python file.
When I run it from the terminal ./Ex02_DriveStatus 5 blablabla.sw
it's working well.But I would like to be able to run it from my flask application/ web interface.
Here is my python code:
import canopen
from datetime import datetime
import time
import os
import numpy as np
import argparse
from DriveLib import Drive
from flask import Flask
from flask import request
from flask import render_template
import subprocess
from subprocess import PIPE
# os.system("sudo ifconfig can0 down")
# os.system("sudo ip link set can0 type can bitrate 500000")
# os.system("sudo ifconfig can0 up")
app = Flask(__name__)
#app.route('/')
def home():
return render_template('flashing.html')
#app.route('/flashing/')
def home_flash():
return render_template('flashing.html')
#app.route('/flashing/', methods=['POST'])
def flash():
global node_id
global file_name
node_id = request.form['node_id']
file_name = request.form['file_name']
if request.form.get("submit"):
node_id = request.form['node_id']
file_name = request.form['file_name']
if node_id == '':
node_id = 0
if file_name == '':
file_name = 0
if request.method == 'POST':
output = run(node_id, file_name)
return render_template('flashing.html', output=output, node_id=node_id, file_name=file_name)
def run(node_id, file_name):
s=subprocess.run(["./Ex02_DriveStatus", node_id, file_name],stdout=PIPE)
print(s)
return s.stdout.decode("utf-8")
And my HTML code:
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" href='/static/main.css'/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type=text/javascript src="{{
url_for('static', filename='main.js') }}"></script>
<script>
window.addEventListener("load", function(){
// BASIC
numpad.attach({target: "demoA"});
// WITH OPTIONS
numpad.attach({target: "demoB"});
numpad.attach({target: "demoC"});
});
</script>
<title>FLASH the drive</title>
<p class="title"><strong>FLASH THE DRIVE</strong></p>
</head>
<body>
<div id="menu">
<ul id="onglets" >
<li class="active"> Flash drive </li>
<li> Test drive </li>
<li> Test module </li>
</ul>
</div>
<div class="content">
<!--test form-->
<form method="post" action="/flashing/">
<textarea id="output" name="output" rows="30" cols="50" style="resize:none" placeholder="//Your output here.">{{output}}</textarea><br>
<table>
<tr>
<td> <p>Chose the ID you want to flash with:</p> </td>
<td> <input name="node_id" id="demoA" style="height:50px;"> </td>
</tr>
<tr>
<td> <p>File name:</p> </td>
<td> <input name="file_name" style="height:50px;"> </td>
</tr>
<tr>
<td> <input id="buttonid" type="submit" name="submit" class="submit" value="FLASH"> </td>
</tr>
</table>
</form>
</div>
</body>
</html>
When I try this flask run it's running for ever without results.
I tried to create a python file test.py with just a print print("hello").
I assume this line is the problem:
s=subprocess.run(["./Ex02_DriveStatus", node_id, file_name],stdout=PIPE)
so I tested it with a simple file (the test.py):
s=subprocess.run(["python", file_name],stdout=PIPE)
and on the file_name input I would enter test.py and it is working.
So I don't know if it is because the executable from c++ gives me some conflict or if there is something I didn't write well.

Make sure your program is outputting to STDOUT.
Try removing the stdout=PIPE or try piping STDERR as well.

Related

How do I embed a Bokeh Interactive Plot in a Flask application?

I am currently trying to create a very simple app that displays a recipe and a network diagram.
I have gotten most of the way there, but I am receiving the following error:
Uncaught ReferenceError: Bokeh is not defined
at HTMLDocument.fn (?description=blueberry+pancakes:29:5)
I have tried implementing the solutions at the following locations:
Python Flask App with Interactive Bokeh plots
Embedding a bokeh plot in Flask
Embedding bokeh plot and datatable in flask
Bokeh plot not visible in flask application
but nothing is really changing.
Below is my current version of index.html.
<html>
<head>
<title>Recipes</title>
<style>
.row {
display: flex;
}
.column {
flex: 50%;
}
</style>
<script scr="https://cdn.pydata.org/bokeh/release/bokeh-3.0.0.min.js"></script>
<script scr="https://cdn.pydata.org/bokeh/release/bokeh-widgets-3.0.0.min.js"></script>
<script scr="https://cdn.pydata.org/bokeh/release/bokeh-tables-3.0.0.min.js"></script>
<script scr="https://cdn.pydata.org/bokeh/release/bokeh-gl-3.0.0.min.js"></script>
<link
href="https://cdn.pydata.org/bokeh/release/bokeh-0.13.0.min.css"
rel="stylesheet" type="text/css">
<link
href="https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.13.0.min.css"
rel="stylesheet" type="text/css">
<link
href="https://cdn.pydata.org/bokeh/release/bokeh-tables-0.13.0.min.css"
rel="stylesheet" type="text/css">
{{script | safe}}
</head>
<!-- <header>
{{ script|safe }}
</header> -->
<body>
<form action="" method="get">
Recipe Description: <input type="text" name="description">
<label for="diets">Choose a Diet:</label>
<select id="diets" name="diet_plan" size="2" multiple>
<option value="Vegan">Vegan</option>
<option value="Vegetarian">Vegetarian</option>
<option value="Nut-Free">Nut-Free</option>
<option value="Gluten-Free">Gluten-Free</option>
</select><br><br>
<input type="submit" value="Generate a recipe">
</form>
<h1>{{description}}</h1>
<h2>{{diet_plan}}</h2>
<div class="row">
<div class="column">
<h2>Ingredients</h2>
<ul>
{%for i in range(0, len)%}
<li>{{ingredients[i]}}</li>
{%endfor%}
</ul>
</div>
<div class="column">
<h2>Instructions</h2>
<ul>
{%for i in range(0, len)%}
<li>{{instructions[i]}}</li>
{%endfor%}
</ul>
</div>
</div>
<h1>{{div}}</h1>
<div>
{{div|safe }}
</div>
</body>
</html>
And here is the main portion of main.py.
from flask import Flask
from flask import request, render_template, send_file
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt
from bokeh.io import output_file, show
from bokeh.models import (BoxZoomTool, Circle, HoverTool, MultiLine, Plot, Range1d, ResetTool)
from bokeh.palettes import Spectral4
from bokeh.plotting import from_networkx, save
from bokeh.embed import components
from bokeh.resources import CDN
from io import BytesIO
import re
app = Flask(__name__)
#app.route("/")
def index():
description = request.args.get("description", "")
# diet_plan = request.form.getlist("diets", "")
diet_plan = request.args.get("diet_plan", "")
if description:
recipe, steps = get_ai_recipe()
ingredients = recipe["ingredient"] + " (" + recipe["qty"] + ")"
instructions = steps["instruction"]
script, div = generate_graph(recipe)
else:
recipe = None
steps = None
ingredients = pd.DataFrame({"ingredient" : []})
instructions = pd.DataFrame({"instruction" : []})
script, div = ("", "")
return render_template("index.html",
len = len(ingredients),
ingredients = ingredients,
instructions = instructions,
description = description,
diet_plan = diet_plan,
script = script,
div = div,
resources = CDN.render())
I didn't include the get_ai_recipe() or generate_graph() functions to save some space, but basically get_ai_recipe() returns 2 pandas dataframes, and generate_graph() returns a script and a div from components.
script, div = components(plot)
return script, div
So the "plot" in that code is an actual "Plot" class from bokeh.models. Pretty much every online example I saw when trying to debug this uses figure() instead of Plot(). I'm not sure if that has anything to do with my issue, but if it does, I would appreciate help in figuring out how to convert the Plot to a figure.
Additionally, I am very new to flask and html (this is my very first interaction with them, really), so I'm not sure what all of the scripts/links in the head section are doing. I also do not know if those are the most recent versions of those links. I used the original version from the examples online and then updated them as far as I could, but I'm not sure if they go any further. Some examples used all of those, and some used just one. I assume this is where my issue lies, but I am not sure.
The code is definitely generating the div, as I have it printed as a title on the page, but it's unable to find bokeh.
I would appreciate any help.
Thanks!
You are already passing the div with the plot,
but cannot tell how, try using bokeh.plotting.Figure and bokeh.embed.components;
import bokeh
# ...
empty_boxplot = bokeh.plotting.Figure(
plot_width=500,
plot_height=450
)
script, div = bokeh.embed.components(empty_boxplot)
you can then render it with Jinja in your index.html
<div id="plot">
{{ div }}
</div>
OK I figured it out.
The solution comes from here
Bokeh plot not visible in flask application
Which is a solution I tried to implement but failed to do so correctly.
Below is the correct solution.
main.py:
from flask import Flask
from flask import request, render_template, send_file
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt
from bokeh.io import output_file, show
from bokeh.models import (BoxZoomTool, Circle, HoverTool, MultiLine, Plot, Range1d, ResetTool)
from bokeh.palettes import Spectral4
from bokeh.plotting import from_networkx, save, figure
from bokeh.embed import components
from bokeh.resources import CDN
from io import BytesIO
import re
app = Flask(__name__)
#app.route("/")
def index():
description = request.args.get("description", "")
# diet_plan = request.form.getlist("diets", "")
diet_plan = request.args.get("diet_plan", "")
if description:
recipe, steps = get_ai_recipe()
ingredients = recipe["ingredient"] + " (" + recipe["qty"] + ")"
instructions = steps["instruction"]
script, div = generate_graph(recipe)
else:
recipe = None
steps = None
ingredients = pd.DataFrame({"ingredient" : []})
instructions = pd.DataFrame({"instruction" : []})
script, div = ("", "")
return render_template("index.html",
len = len(ingredients),
ingredients = ingredients,
instructions = instructions,
description = description,
diet_plan = diet_plan,
script = script,
div = div,
resources = CDN.render())
index.html:
<html>
<head>
<title>Recipes</title>
<style>
.row {
display: flex;
}
.column {
flex: 50%;
}
</style>
{{ resources|safe }}
</head>
<header>
{{ script|safe }}
</header>
<body>
<form action="" method="get">
Recipe Description: <input type="text" name="description">
<label for="diets">Choose a Diet:</label>
<select id="diets" name="diet_plan" size="2" multiple>
<option value="Vegan">Vegan</option>
<option value="Vegetarian">Vegetarian</option>
<option value="Nut-Free">Nut-Free</option>
<option value="Gluten-Free">Gluten-Free</option>
</select><br><br>
<input type="submit" value="Generate a recipe">
</form>
<h1>{{description}}</h1>
<h2>{{diet_plan}}</h2>
<div class="row">
<div class="column">
<h2>Ingredients</h2>
<ul>
{%for i in range(0, len)%}
<li>{{ingredients[i]}}</li>
{%endfor%}
</ul>
</div>
<div class="column">
<h2>Instructions</h2>
<ul>
{%for i in range(0, len)%}
<li>{{instructions[i]}}</li>
{%endfor%}
</ul>
</div>
</div>
<h1>{{div}}</h1>
<div>{{div|safe }}</div>
</body>
</html>

Flask - Edit Prefilled Table Value and Resubmit

Overview
I am currently building a Flask application where a user will a upload a book cover and the OCR machine learning model will attempt to read the title and author of the book from the cover. The results are then shown in a html table. If the model is incorrect I want the user to be able to edit the data in the table and send it back to the flask app to be stored in the database.
I have tried a few solution such as placeholders and other solutions provided from stack overflow but none seem to allow me edit the data and submit the updated table. below are the solutions I have tried
Flask get and edit values
Send table data via form to Flask method
HTML
<link rel="stylesheet" href="{{ url_for('static', filename = 'styles/styles.css') }}">
<h1>Book Details</h1>
<body>
<img src="{{ image }}" alt="User Image" width="100%" height="100%" class="imagecenter">
</body>
&nbsp
<form action="{{ url_for('book_details') }}" method="post">
<table id = "bookDetails">
<tr>
<th> Title </th>
<td name="booktitle" contenteditable='true'>{{bookDetails['Title']}}</td>
<input type="hidden" name="booktitle" type="text" value="{{bookDetails['Title']}}"td>
</tr>
</table>
<p><input type="submit" value="Save to Database" class="uploadButton"></p>
</form>
Python
#app.route('/bookDetails', methods=["POST", 'GET'])
def book_details():
if request.method == "POST":
bookid = request.form["booktitle"]
print(bookid)
return render_template('book_details.html', bookDetails=exampleBookDetails, image = 'static/why_nations_fail.jpg')
Output
I am either getting the same value as originally given or the name of the field
Why Nations Fail
or
booktitle
When it needs to be "Why Nations Fail extra text".

How to return flask output to the same html page

I have an html file which reads like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Robots Uploader</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<section id="content">
<section class="module w100P">
<div id="error_bar" style = "display:none" class="message-bar error">
<p><span class="icon">Error:</span> Uh-oh, something broke! Close</p>
</div>
<div id="success_bar" style="display:none" class="message-bar success">
<p><span class="icon">Success:</span> Your changes have been made. Close</p>
</div>
<div class="module-inner">
<h3>DailyHunt Robots Uploader</h3>
<div class="module-content frm">
<form action="http://localhost:5000/uploadFile" method="post" enctype="multipart/form-data">
<table>
<tr>
<td>
<select name ="domain">
<option selected>Select Domain</option>
<option value="m">m</option>
<option value="www">www/option>
</select>
</td>
<td>
<input type="file" name="robots" accept='robots.txt'>
<button type="submit">Upload</button>
</td>
</tr>
</table>
</form>
<form action="http://localhost:5000/uploadApk" method="post" enctype="multipart/form-data">
<table>
<tr>
<td>
Enter APK you want to upload:
</td>
<td>
<input type="file" name="apk">
<button type="submit">Upload</button>
</td>
</table>
</form>
</div>
</div>
</section>
</section>
</section>
</body>
</html>
on hitting submit, it hits the flask api engine, where the 2 functions to be hit are defined as
#app.route('/uploadFile', methods=['POST'])
def upload_robots():
domain = request.form.get('domain')
if not domain:
return "Domain does not exist"
f = request.files[ROBOTS_IDENTIFIER]
if f.filename!=ROBOTS_FILE_NAME:
return "Incorrect file name. File name has to be robots.txt"
if domain == 'm':
robots_file_path = ROBOTS_MOBILE_FILE_PATH
elif domain == 'www':
robots_file_path = ROBOTS_WEB_FILE_PATH
else:
return "Domain not recognized"
filename = secure_filename(f.filename)
if os.path.isfile(robots_file_path + ROBOTS_FILE_NAME):
folder_name = datetime.utcfromtimestamp(int(os.path.getmtime(robots_file_path + ROBOTS_FILE_NAME))).strftime('%Y-%m-%d %H:%M:%S')
os.makedirs(robots_file_path + folder_name)
shutil.move(robots_file_path + ROBOTS_FILE_NAME, robots_file_path + folder_name +'/' + ROBOTS_FILE_NAME)
f.save(os.path.join(robots_file_path, ROBOTS_FILE_NAME))
return "file uploaded successfully, This will reflect in prod after the next cron cycle"
#app.route('/uploadApk', methods=['POST'])
def upload_apk():
f = request.files[APK_IDENTIFIER]
if f.filename.split('.')[-1] != 'apk':
return "upload file type must be apk"
filename = secure_filename(f.filename)
fname = '.'.join(f.filename.split('.')[0:-1])
rename = False
while os.path.isfile(APK_FILE_PATH + fname + '.apk'):
rename = True
fname += '_'
if rename:
shutil.move(APK_FILE_PATH + f.filename, APK_FILE_PATH + fname + '.apk')
f.save(os.path.join(APK_FILE_PATH, filename))
return "APK uploaded successfully"
Now when I hit submit the api returns some texts and it gets directed to a new page with just the text rendered. I would like this to remain in the same page and display the error_bar or success_bar divs in the html rather than it being redirected to a new page. Is it possible to achieve this without rendering a template or creating a new static html page?
Let's assume that your current page is: index.html.
I thought about two ways for resolving.
The first way,
After making request to your API, just render_template index.html again, including extra data (error=True/False, message=...) and you have update your index.html to check condition when receive extra data to display the error/success message.
=> By this way, you should modify the template and use Flask's render_template.
I prefer this way because of having control of the template (index.html) it just needs small update.
The second way, make request by using AJAX (XHR), when click submit button, you prevent the default form submit and use AJAX to request, then receive response and display the message.
The AJAX script can stay in index.html or another *.js where your index.html can locate.
=> By this way, you are working in non-Flask dependent way, by using Ajax you make request and modify the document (index.html) by using a little Javascript.

OS Error : Error No 22

This is the error :
127.0.0.1 - - [22/Jun/2015 17:15:21] "POST /cgi-bin/get_tran_data.py HTTP/1.1" 2
00 -
127.0.0.1 - - [22/Jun/2015 17:15:21] command: C:\Python34\python.exe -u C:\Pytho
n34\ProjectShivam\webapp\cgi-bin\get_tran_data.py ""
127.0.0.1 - - [22/Jun/2015 17:15:22] b'Traceback (most recent call last):\r\n F
ile "C:\\Python34\\ProjectShivam\\webapp\\cgi-bin\\get_tran_data.py", line 20, i
n <module>\r\n with open("C:\\Python34\\ProjectShivam\\webapp\\cgi-bin\\tran_
add_success.py") as g:\r\nOSError: [Errno 22] Invalid argument: \'C:\\\\Python34
\\\\ProjectShivam\\\\webapp\\\\cgi-bin\\tran_add_success.py\'\r\n'
127.0.0.1 - - [22/Jun/2015 17:15:22] CGI script exit status 0x1
get_tran_data.py:
import cgi
import yate
import sqlite3
import sys
connection = sqlite3.connect('users.sqlite')
cursor = connection.cursor()
print('Content-type:text/html')
form=cgi.FieldStorage()
doctype=form['doctype'].value
docno=form['docno'].value
docdate=form['docdate'].value
bincard=form['bincard'].value
rate=form['rate'].value
quantity=form['qty'].value
cursor.execute("INSERT INTO TRAN(DOCTYPE,DOCNO,DOCDATE,BINCARD,QTY,RATE) VALUES (?,?,?,?,?,?)",(doctype,docno,docdate,bincard,rate,quantity))
connection.commit()
with open("C:\Python34\ProjectShivam\webapp\cgi-bin\tran_add_success.py") as g:
code = compile(g.read(),"tran_add_success.py", 'exec')
exec(code)
When i remove the open statement from get_tran_data.py, the script runs successfully. I used a similar open statement in another script and that ran successfully but here i don't know what is the problem?
EDIT:
This is get_opb_data.py, the script with similar code but runs successfully:
import cgi
import yate
import sqlite3
import sys
connection = sqlite3.connect('users.sqlite')
cursor = connection.cursor()
print('Content-type:text/html')
form=cgi.FieldStorage()
bincard=form['bincard'].value
desc=form['desc'].value
loc=form['loc'].value
qty=form['qty'].value
rate=form['rate'].value
Value=form['value'].value
currate=form['currate'].value
curqty=form['curqty'].value
cursor.execute("INSERT INTO OPB(Bincard,Description,Location,Quantity,Rate,Value,CurRate,CurQty) VALUES (?,?,?,?,?,?,?,?)",(bincard,desc,loc,qty,rate,Value,currate,curqty))
connection.commit()
with open("C:\Python34\ProjectShivam\webapp\cgi-bin\opb_add_success.py") as f:
code = compile(f.read(), "opb_add_success.py", 'exec')
exec(code)
Also, the tran_add_success.py file exists, I have made sure of that. I don't get why this is happening, that once script is running just fine and the other isnt.
tran.html:
<html>
<head>
<title>Transaction</title>
<link type="text/css" rel="stylesheet" href="coach.css" />
</head>
<body>
<img src="images/logo-cel-transparent_0.png" width="74" height="64"><strong><img src="images/logo-cel-transparent_0.png" alt="Cel logo" width="74" height="64" align="right">
</strong>
<h1 align="center"><strong>Central Electronics Limited</strong></h1>
<p> </p>
<h2 align="center">Storage Management System</h2>
<p> </p>
<div align="center"><strong>Transaction!!</strong></div>
<p align="left"> </p>
<p align="center">
<form action="cgi-bin/get_tran_data.py" method="post">
<div align="center">DocType :
<input type="text" name="doctype">
DocNo :
<input type="text" name="docno">
DocDate :
<input type="text" name="docdate">
<br><br>
BinCard :
<input type="text" name="bincard">
Rate :
<input type="text" name="rate">
Quantity :
<input type="text" name="qty">
<br>
<p align="center"><input type="submit" value="Submit"></p>
</div>
</form>
</p>
</body>
</html>
When i click the submit button on tran.html, the get_tran_data.py runs. Now it fetches the data from the form and saves it to database. I use open statement in get_tran_data.py so as to run another script which displays a success message on the screen.

Flask submit form and show inserted values

I am completely new to python and Flask and I am trying to run in my computer the code showed in this page:
http://runnable.com/UhLMQLffO1YSAADK/handle-a-post-request-in-flask-for-python
This are the steeps I follow and the code:
1-I have installed Flask
2-Files
File app.py
# We need to import request to access the details of the POST request
# and render_template, to render our templates (form and response)
# we'll use url_for to get some URLs for the app on the templates
from flask import Flask, render_template, request, url_for
# Initialize the Flask application
app = Flask(__name__)
# Define a route for the default URL, which loads the form
#app.route('/')
def form():
return render_template('form_submit.html')
# Define a route for the action of the form, for example '/hello/'
# We are also defining which type of requests this route is
# accepting: POST requests in this case
#app.route('/hello/', methods=['POST'])
def hello():
name=request.form['yourname']
email=request.form['youremail']
return render_template('form_action.html', name=name, email=email)
# Run the app :)
if __name__ == '__main__':
app.run(
host="0.0.0.0",
port=int("80")
)
File form_action.html
<html>
<head>
<title>Handle POST requests with Flask</title>
<link rel=stylesheet type=text/css href="style.css">
</head>
<body>
<div id="container">
<div class="title">
<h1>POST request with Flask</h1>
</div>
<div id="content">
Hello <strong>{{name}}</strong> ({{email}})!
</div>
</div>
</div>
</body>
</html>
File form_submit.html
<html>
<head>
<title>Handle POST requests with Flask</title>
<link rel=stylesheet type=text/css href="style.css">
</head>
<body>
<div id="container">
<div class="title">
<h1>POST request with Flask</h1>
</div>
<div id="content">
<form method="post" action="{{ url_for('hello') }}">
<label for="yourname">Please enter your name:</label>
<input type="text" name="yourname" /><br />
<label for="youremail">Please enter your email:</label>
<input type="text" name="youremail" /><br />
<input type="submit" value="Send" />
</form>
</div>
</div>
</div>
</body>
</html>
3-I run the py file:
sudo python app.py
[sudo] password for jose:
* Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
When I open the browser I write:
file:///home/jose/Escritorio/python/app/form_submit.html
I insert the data in the 2 forms and I press Send and this is what happens:
URL: file:///home/jose/Escritorio/python/app/{{url_for('hello')}}
Web Page: File not found
What am I doing wrong?
0.0.0.0 means that you can access the flask website from outside of the website host. Use the host ip plus the port # you specified
http://:80/hello in your case. That should display the form_action.html you specified in your routes.
If you want save form data, your code didn't work. You must have a database or save in a file.

Categories