Flask - Errno 13 权限被拒绝

2 投票
2 回答
3165 浏览
提问于 2025-04-18 06:48

我正在写一个小网页,目的是让用户上传他们的文件,同时在上传时我想运行一个用Python写的计算程序,这样就能给用户输出结果。

我的代码大概是这样的:

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')

上传的过程很顺利,但问题是当我点击上传时,出现了一个信息 OSError: [Errno 13] Permission denied,导致这个问题的代码行是:

subprocess.call(['/home/martyna/Dropbox/programowanie/project_firefox/topologia.py', '/uploads/2014-05-16T22:08:19.522441'])

程序 topologia.py 是通过命令 python topologia.py input_file 来运行的。

我不知道该怎么解决这个问题。

2 个回答

0

从命令行和服务器执行脚本时,权限是不同的。

user@mycomputer:~$ ./script

在这个例子中,./script 是由 user 来运行的。如果这个脚本需要进行一些输入或输出操作,那么它的访问权限就取决于 user 的权限。

而当是服务器来运行这个脚本,比如你用的 Flask,那么通常是 www-data 来启动这个脚本。所以,访问权限就不一样了。

因此,要在一个文件夹里创建文件,执行脚本的用户必须对这个文件夹有权限。

2

你遇到了两个问题:

  • 你的脚本可能没有被标记为可执行的。你可以通过使用当前的Python可执行文件路径来解决这个问题;可以用sys.executable来获取这个路径。

  • 你告诉脚本去处理/uploads/proper_filename,但你实际上传文件时用的文件名根本不一样;你应该使用proper_filename所指向的字符串内容。

把这两点结合起来:

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])

不需要run_script()的结果上调用.start();这样会导致NoneType的属性错误。只需直接调用run_script(),就可以了:

run_script()

撰写回答