cv2.imread is blocking flow - python

am trying to read an image using cv2.imread() but the flow just block there and never returns, tried to read already-existing files but got same issue, am not sure what is the reason is
#app.route('/api/upload', methods=['GET', 'POST'])
def upload_file():
print('request method is {}'.format(request.method))
if request.method == 'POST':
# check if the post request has the file part
if 'file' not in request.files:
print('file not in request.files')
return redirect(request.url)
file = request.files['file']
if file.filename == '':
print('filename is {}'.format(file.filename))
return redirect(request.url)
print(file and allowed_file(file.filename))
if file and allowed_file(file.filename):
print('receiving ... ', file.filename)
filename = secure_filename(file.filename)
ts = int(time.time())
file_name = file_name_template.format(ts, filename)
print(file_name)
filePath = os.path.join(app.root_path, app.config['UPLOAD_FOLDER'], file_name)
file.save(filePath)
print('reading image')
cv2.imread(filePath)
return 'done' #never executed
note : this is a flask application running on WAMP server + WSGI

I believe this has been answered already in another posting. Also see http://blog.rtwilson.com/how-to-fix-flask-wsgi-webapp-hanging-when-importing-a-module-such-as-numpy-or-matplotlib/.
Basically, it's not using the main interpreter to run the cv2.imread, which isn't running properly in a sub-interpreter.

Related

API works with only 1 file type?

I have a C# script that uploads a video to a Flask API, the API processes the video using openCV and it creates and sends back a text file. The only issue is, it only seems to work with the .qt filetype, and any other video I send will not work properly (mov, mp4, etc). The API receives a valid video, or so it says, but it is as if the video comes across totally empty with no data in it. The text file it creates is blank because it seemingly is processing nothing. There is nothing in either script that makes the .qt file only work, and I have tried everything including tinkering with the 'MediaTypeHeaderValue.' I am absolutely stumped. Also, I am posting again because my first post on stack overflow wasn't good enough or had all the scripts, so I am just starting over. I'll post the C# script to upload the video, the Python script to process it, and the requirements.txt.
C# Code
using System.Net.Http.Headers;
var filePath = "run.mp4";
using var client = new HttpClient();
using (var multipartFormContent = new MultipartFormDataContent())
{
//Add the file
var fileStreamContent = new StreamContent(File.OpenRead(filePath));
fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue("video/mp4");
multipartFormContent.Add(fileStreamContent, name: "file", fileName: "run.mp4");
//Send it
var response = await client.PostAsync("http://127.0.0.1:5000/", multipartFormContent);
//Ensure it was successful.
response.EnsureSuccessStatusCode();
//Grab the animation data from the content.
var animation_data = await response.Content.ReadAsStringAsync();
//Save to file.
await File.WriteAllTextAsync("AnimationFile.txt", animation_data);
}
Python Code Below
from flask import Flask, request, redirect, url_for, send_from_directory, request
from werkzeug.utils import secure_filename
import cv2
from cvzone.PoseModule import PoseDetector
UPLOAD_FOLDER = 'uploads'
ALLOWED_EXTENSIONS = {'3gp', 'mov', 'qt', 'avi', 'wmv', 'mp4'}
app = Flask(__name__)
app.config["DEBUG"] = True
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MAX_CONTENT_LENGTH'] = 16 * 1000 * 1000 # Limit upload size to 16 megabytes per file.
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
#app.route('/uploads/<name>')
def download_file(name):
return send_from_directory(app.config["UPLOAD_FOLDER"], name)
#app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
if 'file' not in request.files:
return redirect(request.url,400, "File part not found in request.")
file = request.files['file']
if file.filename == '':
return redirect(request.url,400, "Filename is empty.")
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
cap = cv2.VideoCapture(filename)
detector = PoseDetector()
posList = []
while True:
success, img = cap.read()
if img is None:
break
img = detector.findPose(img)
lmList, bboxInfo = detector.findPosition(img)
if bboxInfo:
lmString = ''
for lm in lmList:
lmString += f'{lm[1]},{img.shape[0] - lm[2]},{lm[3]},'
posList.append(lmString)
# file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) Don't need to save the file
with open("uploads/AnimationFile.txt", 'w') as f:
f.writelines(["%s\n" % item for item in posList])
return redirect(url_for('download_file', name="AnimationFile.txt"))
return '''<h1>Test Api!</h1>'''
app.run()
Requirements.txt
absl-py==1.2.0
attrs==22.1.0
click==8.1.3
cvzone==1.5.6
cycler==0.11.0
Flask==2.2.2
fonttools==4.37.1
itsdangerous==2.1.2
Jinja2==3.1.2
kiwisolver==1.4.4
MarkupSafe==2.1.1
matplotlib==3.5.3
mediapipe==0.8.10.1
numpy==1.23.2
opencv-contrib-python==4.6.0.66
opencv-python==4.6.0.66
packaging==21.3
Pillow==9.2.0
protobuf==3.20.1
pyparsing==3.0.9
python-dateutil==2.8.2
six==1.16.0
Werkzeug==2.2.2

Uploading xml file and processing using flask

I am developing a Python backend to which I send an xml file from the front end. This is so that I can generate python code based on it and show the contents in the front end. How can I do this using flask?
I have attached the code I tried below. It does not work for me. I was not able to save the xml file into a directory.
from flask import Flask, request, render_template
app = Flask(__name__, template_folder='templates')
from main import run
import os
#app.route('/')
def home():
return render_template('home.html')
#app.route('/submit/', methods=['POST'])
def upload():
if request.method == 'POST':
uploaded_file = xmltodict.parse(request.get_data())
file = os.path.join(app.config['upload'].uploaded_file.filename)
uploaded_file.save(file)
return "Successfully uploaded"
#app.route('/submit/')
def convert():
path='upload'
os.chdir(path)
for file in os.listdir():
if file.endswith(".py"):
file_path = f"{path}\{file}"
run(file_path,'tmp','python')
return "Code generated"
#app.route('/view/')
def view_python_script():
# Folder path
path='tmp'
os.chdir(path)
content=""
for file in os.listdir():
if file.endswith(".py"):
file_path = f"{path}\{file}"
with open(file_path, "r") as f:
content = content + f.read().replace('\n','<br>')
return render_template('upload.html', details=content)
if __name__ == "__main__":
app.run(port=3000, debug=True)
I occupy this: uploaded_file = request.files ['file_upload'].
file_upload I pass it from the html with the parameter name = "file_upload" of input contained within the form.
The problem I have is that when I want to share it in another html page it closes and throws me a ValueError: I / O operation on closed file.
But well, I hope it helps you !!!

How to rename upload image while uploading - Flask / Python

I´m building a website where people should be able to add small adds with pictures. All pictures go to the same directory. So I need to rename the pictures so there wont be any overrides or conflicts.
When I´m adding an add to the website its auto increment the add_id. I want to use this add_id for the picture name.
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
#app.route('/aufgeben', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
titel = request.form['titel']
beschreibung = request.form['beschreibung']
kategorie = request.form['kategorie']
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
# submit a empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
# Anzeigeninhalt in DB eintragen
cursor = g.con.cursor()
cursor.execute('insert into anzeigen (titel, beschreibung, kategorie) values (%s, %s, %s)',
(titel, beschreibung, kategorie))
g.con.commit()
cursor.close()
flash("Anzeige aufgegeben.")
return render_template('aufgeben.html',)
Thanks for all help. Maybe someone have a better idea how to solve this?
I know it might be too late for a response but maybe someone else will look for an answer. As Nishant Nawarkhede replied, you can use timestamp to rename the files uploaded. Since I came accross the same need I used the following piece of code to rename the files while uploading:
NOW = datetime.datetime.now()
new_filename = os.path.join(UPLOAD_FOLDER, file.filename.rsplit('.',1)[0] + '_' + NOW.strftime("%d_%m_%Y_%H_%M_%S") + '.' + file.filename.rsplit('.',1)[1])
After this, your files should look like the following format:
'path_to_file/filename_datetime.jpg'

Flask won't continue to execute after redirect

I'm new to Flask. I want to create a simple project that I can upload the file to web, call the exe program to process the file and output the log of the process. I tried to modified a little the template for file upload from http://flask.pocoo.org/docs/0.12/patterns/fileuploads/ to implement with the features I want.
I managed to browse and save the file to my directory, but I couldn't run the processing_call method. However, I tried refresh the page and found that it can run the exe program. This means that processing_call works. But what I want is to call the exe without the need to refresh the page.
This is my code:
#app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
# submit a empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return redirect(url_for('uploaded_file',
filename=filename))
processing_file()
return render_template('uploadfile.html',subprocess_output=processing_file())
In Python language, code after return statement will never work (it is same in all languages as I know). So if you need to do something, execute it before return. If you don't want to block user while executing function, you will need task queue (https://www.fullstackpython.com/task-queues.html) to make call it asynchronously.

Reading input file and processing it in flask

I'm trying to write a simple flask program that will create a web page in which it receives a file (by uploading it), and then using that file's data and displaying a filtered part of it in my web page, I just cant seem to understand how to do that.
This is the code I used to upload the file, which worked fine.
import os
from flask import Flask, request, redirect, url_for
from werkzeug.utils import secure_filename
UPLOAD_FOLDER = 'C:/Users/ohadt/PycharmProjects/logFiles'
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif', 'log'])
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
#app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
# submit a empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return redirect(url_for('read_uploaded_file',
filename=filename))
return '''
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<form action="" method=post enctype=multipart/form-data>
<p><input type=file name=file>
<input type=submit value=Upload>
</form>
'''
Then I tried writing the method for opening the file and reading the data from it, but I couldn't figure how to do that, could you please help me understand how to read the file content and presenting a filtered version of it on my site?
Thanks!
You already saved it here
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
just open it up and read as you work with any other files, example:
#app.route('/read_file', methods=['GET'])
def read_uploaded_file():
filename = secure_filename(request.args.get('filename'))
try:
if filename and allowed_filename(filename):
with open(os.path.join(app.config['UPLOAD_FOLDER'], filename)) as f:
return f.read()
except IOError:
pass
return "Unable to read file"
You need to carefully sanitize user input here, otherwise method could be used to read something unintended (like app source code for example). Best is just not grant user ability to read arbitrary files - for example when you save a file, store it's path in database with some token and give user just this token:
filename = secure_filename(file.filename)
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(filepath)
token = store_in_db(filepath)
return redirect(url_for('read_uploaded_file',
token=token))
Then accept a token, not a filename when you read a file:
#app.route('/read_file', methods=['GET'])
def read_uploaded_file():
filepath = get_filepath(request.args.get('token'))
try:
if filepath and allowed_filepath(filepath):
with open(filepath) as f:
return f.read()
except IOError:
pass
return "Unable to read file"
Tokens need to be random, long, not guessable (uuid4 for example) - otherwise there will be a possibility to easily read other users files. Or you need to store relation between file and user in database and check it too. Finally, you need to control size of file uploads to prevent user from uploading huge files (app.config['MAX_CONTENT_LENGTH']) and control amount of info you read in memory when you display "filtered" file content (f.read(max_allowed_size)).

Categories