Flask - Errno 13 premission denied - python

I'm writing a small web page whose task is to let a user upload his input file and with uploading I want to execute my calculation program in python which will give me output for the user.
My code looks like this:
import os
import os.path
import datetime
import subprocess
from flask import Flask, render_template, request, redirect, url_for
from werkzeug import secure_filename
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['ALLOWED_EXTENSIONS'] = set(['txt', 'gro', 'doc', 'docx'])
current_time = datetime.datetime.now()
file_time = current_time.isoformat()
proper_filename = file_time
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in app.config['ALLOWED_EXTENSIONS']
def run_script():
subprocess.call(['/home/martyna/Dropbox/programowanie/project_firefox/topologia.py', '/uploads/proper_filename'])
#app.route('/')
def index():
return render_template('index.html')
#app.route('/upload', methods = ['POST'])
def upload():
file = request.files['file']
if file and allowed_file(file.filename):
file.save(os.path.join(app.config['UPLOAD_FOLDER'], proper_filename))
run_script().start()
return "Thank you for uploading"
if __name__ == '__main__':
app.debug = True
app.run(host='0.0.0.0')
Uploading goes well, but the problem is that when I hit upload I get message OSError: [Errno 13] Permission denied and the line causing the problem is:
subprocess.call(['/home/martyna/Dropbox/programowanie/project_firefox/topologia.py', '/uploads/2014-05-16T22:08:19.522441'])
program topologia.py runs from command python topologia.py input_file
I have no idea how to solve that problem.

You have two problems:
Your script is probably not marked as executable. You can work around that by using the current Python executable path; use sys.executable to get the path to that.
You are telling the script to process /uploads/proper_filename, but the filename you actually upload your file to is not the same at all; you should use the contents of the string referenced by proper_filename instead.
Put these two together:
import sys
from flask import current_app
def run_script():
filename = os.path.join(current_app.config['UPLOAD_FOLDER'], proper_filename)
subprocess.call([
sys.executable,
'/home/martyna/Dropbox/programowanie/project_firefox/topologia.py',
filename])
You do not need to call .start() on the result of run_script(); you'll get an attribute error on NoneType. Just call run_script() and be done with it:
run_script()

Executing a script from a command line and from a server will not be done with the same permissions.
user#mycomputer:~$ ./script
In this exemple, ./script is launched by user. So if it does some inputs/outputs, the access rigths will depend on user rights.
When it is a server that runs the script, in your case Flask, it is probably www-data that launch the script. So the access rights are not the same.
So to create a file into a folder the user executing the script should have the permissions on the folder.

Related

how to use relative paths instead of full paths in windows using python

I was wondering how to use relative paths instead of full paths in python. in Linux it is ok but in windows when I try using ./ to indicate relative path it throws me an error saying FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\Ender_Bender\\page\\index.html'. here is my code:
from flask import Flask
from os.path import abspath
app = Flask(__name__)
htmlCode = open(abspath('./page/index.html'),'r')
#app.route("/")
def index():
return f"""
{htmlCode}
"""
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
how do I fix this?
Following should work:
from os.path import abspath
import os
dirpath = os.path.dirname(os.path.realpath(__file__))
print (dirpath + "\n")
path = os.path.join(dirpath, 'page/index.html')
print (path + "\n")

Getting exception while opening files in flask

I'm getting error when i make postman request to my api when trying to read files from a directory.
cwd = os.getcwd()
print(cwd)
cwd = cwd.replace('\\','/')
print(cwd)
path = cwd + "/training_data/"
print(path)
try:
for files in os.listdir(path):
data = open(path + files,'r').readlines()
bot.train(data)
except Exception as e:
return jsonify("Error while opening file",path,cwd,os.listdir(path))
I'm getting the following exception:
[
"Error while opening file",
"C:/Users/RakeshS/Desktop/app/training_data/",
"C:/Users/RakeshS/Desktop/app",
[
"code.txt",
"deputation1.txt",
"football.txt",
"Greeting.txt",
"internetaccess.txt",
"intravels.txt",
"sentiment.txt",
"system.txt"
]]
Why is it not able to open the file and read data when i'm getting all the list of files inside the directory?
Here is complete solution to your problem:
from flask import Flask, jsonify
import os
app = Flask(__name__)
#app.route('/')
def hello_world():
cwd = os.getcwd()
path = os.path.join(os.getcwd(), 'training_data')
try:
for file in os.listdir(path):
path_and_file = os.path.join(path, file)
data = open(path_and_file, 'r').readlines()
print(data) # To print everything from a file
return jsonify("Files successfully opened", path, cwd, os.listdir(path))
except:
return jsonify("There was error opening files", path, cwd, os.listdir(path))
if __name__ == '__main__':
app.run()
Here is the output:
Explanation:
In my example, I put it on / route, but you can put it where ever you want.
Whenever I go to / route, I get JSON response. os.getcwd() gets me current directory, but I join two paths using os.path.join() function. From python documentation:
Join one or more path components intelligently.
You can read more on python documentation. Next, since I get the path to training_data, I need to join again path to training_data and file. And I return JSON data. If anything goes wrong, you can print traceback in except clause and also return data, so that flask doesn't raise error for returning no response to the user.
P.S.
training_data folder is in a same level as a your flask application.

Check if a file already exists in a particular folder [duplicate]

This question already has answers here:
How can I safely create a directory (possibly including intermediate directories)?
(28 answers)
Safely create a file if and only if it does not exist with Python
(3 answers)
Closed 4 years ago.
I want, before uploading a file in image folder, to check if the file in the folder already exists or not. If the file already exists it should show a message.
from flask import Flask, render_template, request
from werkzeug import secure_filename
UPLOAD_FOLDER = '/path/to/the/uploads'
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'GIF'])
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
import os, os.path
APP_ROOT = os.path.dirname(os.path.abspath(__file__))
UPLOAD_FOLD = '/python/image/'
UPLOAD_FOLDER = os.path.join(APP_ROOT, UPLOAD_FOLD)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
#app.route('/upload')
def load_file():
return render_template('upload.html')
#app.route('/uploader', methods = ['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['file']
f.save(os.path.join(app.config['UPLOAD_FOLDER'],secure_filename(f.filename)))
return 'file uploaded successfully'
if __name__ == '__main__':
app.run(debug = True)
You can check whether a path exists or not by using os.path.exists method, it returns True if the path passed as a parameter exists and returns False if it doesn't.
For instance: If you want to check if there is any file named hello.c in the current working directory, then you can use the following code:
from os import path
path.exists('hello.c') # This will return True if hello.c exists and will return False if it doesn't
Or You can use the absolute path too
For instance: If you want to check if there is any folder named Users in your C drive then you can use the following code:
from os import path
path.exists('C:\Users') # This will return True if Users exists in C drive and will return False if it doesn't

For loop not working as expected inside python flask

HI i have a small python script which untars a list of files present in a folder.Below is the script.
app = Flask(__name__)
#app.route('/untarJson')
def untarJson():
outdir="C:\\Users\\esrilka\\Documents\\Tar Files\\Untar"
inputfilefolder="C:\\Users\\esrilka\\Documents\\Tar Files\\New tar files\\"
jsonfiles=[]
for filenames in os.listdir(inputfilefolder):
if filenames.endswith(".tar.gz"):
head,tail= os.path.split(filenames)
basename=os.path.splitext(os.path.splitext(tail)[0])[0]
t = tarfile.open(os.path.join(inputfilefolder,filenames), 'r')
for member in t.getmembers():
if "autodiscovery/report.json" in member.name:
with open(os.path.join(outdir,basename + '.json' ), 'wb') as f:
f.write(t.extractfile('autodiscovery/report.json').read())
if __name__ == '__main__':
app.run(debug=True)
It works fine without flask and in the folder i have four tar files and all 4 files are untarred.
But when i use flask only one file is untarred and the only one file name is displayed.
how can i untar all files inside a folder and also return the name of the files(i.,. only short names and not with full path)
See if the below code works for you, I have changed only little bit to your original code and it works without any issues. All the available tar.gz files are untared and file names gets displayed after request completes,
from flask import Flask, jsonify
import tarfile
import os
app = Flask(__name__)
#app.route('/untarJson')
def untarJson():
outdir = "C:\\tests\\untared"
inputfilefolder = "C:\\tests"
jsonfiles = []
for filenames in os.listdir(inputfilefolder):
if filenames.endswith(".tar.gz"):
head, tail = os.path.split(filenames)
basename = os.path.splitext(os.path.splitext(tail)[0])[0]
t = tarfile.open(os.path.join(inputfilefolder, filenames), 'r')
for member in t.getmembers():
if "autodiscovery/report.json" in member.name:
with open(os.path.join(outdir, basename + '.json'), 'wb') as f:
f.write(t.extractfile('autodiscovery/report.json').read())
jsonfiles.append(os.path.join(outdir, basename + '.json'))
return jsonify(jsonfiles), 200
if __name__ == '__main__':
app.run(debug=True)
After request completed, something like below will be returned (output will be different in your case),
[
"C:\tests\untared\autodiscovery1.json",
"C:\tests\untared\autodiscovery2.json",
"C:\tests\untared\autodiscovery3.json"
]

Use url_for to create link to an excel file in output folder

I have one question about url_for Unable to open files in python flask- 404 not found. but was marked duplicate.
My requirement is very simple. To create an href link in the main page pointing to a file in the output folder. I tried almost all threads in SO for the answer seems not working for me. Im very new to python . Please help. Below is a sample code i have tried
from flask import Flask, redirect, url_for,send_from_directory
app = Flask(__name__)
#app.route('/main')
def index():
print 'test'
return '''Open file'''
#app.route('/out/<filename>')
def uploaded_file(filename):
print filename
return send_from_directory('./out/',
filename)
#app.route('/out/<filename>')
def uploaded_file2(filename):
print filename
return './out/'+filename
if __name__ == '__main__':
app.run(debug = True)
your app directory structure should be like this so this code would work. If the filename was not found in out folder then you will see "url not found":
app/
app.py
static/
out/
a.txt
templates/
index.html
from flask import Flask, render_template, redirect, url_for,send_from_directory
app = Flask(__name__)
app.config.update(
UPLOAD_FOLDER = "static/out/"
)
#app.route('/main')
def index():
print ('test')
return render_template('index.html')
#app.route('/out/<filename>')
def uploaded_file(filename):
print (filename)
return send_from_directory(app.config["UPLOAD_FOLDER"], filename)
#app.route('/showfilepath/<filename>')
def uploaded_file2(filename):
print (filename)
return app.config["UPLOAD_FOLDER"] + filename
if __name__ == '__main__':
app.run(debug = True)
# index.html
open file
# a.txt
hey there ...

Categories