如何在Flask / python app.py或views.py文件中提供,引用和保存静态文件,避免FileNotFound错误

问题描述 投票:0回答:2

类似于这个问题,但是我有一些后续措施。 How to serve static files in Flask

我在调整上一篇文章中的解决方案时遇到的主要问题是,我需要使用matplotlib的.savefig()函数,该函数只需要输入一个字符串即可保存到其中。所以我需要知道要传递什么字符串。

我记得在本地首次使用Flask应用程序时,静态文件存在很多问题。我不知道该如何正确地从我的app.py /views.pypython文件引用静态文件的路径。我知道在html中使用url_for(),但不是,但是在python中引用静态文件并不是那么简单。

我的烧瓶应用程序具有以下结构。根目录称为Neuroethics_Behavioral_Task

enter image description here

我有一个名为experiment.py的文件,该文件基本上是views.pyapp.py文件。但是我似乎找不到正确的引用静态文件的方法。

这里是experiment.py代码。

import functools

from flask import (
    Blueprint, flash, g, redirect, render_template, request, session, url_for, Flask
)
from werkzeug.security import check_password_hash, generate_password_hash


app = Flask(__name__, instance_relative_config=True, static_url_path='') # creates the flask instance

bp= Blueprint('experiment', __name__)


@app.route('/')
@app.route('/index')
def index():
    return render_template("welcome.html")

@app.route('/experiment_app', methods=['GET', 'POST'])
def exp_js_psych_app():
    total_trials = int(request.form['trials'])
    import random 
    import string 
    user_id = ''.join([random.choice(string.ascii_letters 
                + string.digits) for n in range(8)]) 
    user_id = str(user_id)
    stim_metadata = generate_stim_for_trials(total_trials, user_id)
    return render_template("index.html", data={"user_id": str(user_id), "total_trials":total_trials, "lst_of_stim_jsons":stim_metadata})
def generate_stim_for_trials(trials, uid):
    import matplotlib
    import matplotlib.pyplot as plt
    import pandas as pd
    import numpy as np
    import json
    import os
    json_dict = {}
    json_dict["stimuli path info"] = []
    lst_of_jsons_for_stimuli = []
    # Unused but problematic static reference.
    stim_metadata_path = "/static/textdata/stimulus_data" + str(uid) + ".json"
    # Another problematic static reference.
    stimuli_path = '/static/images/stimulus_img' + 1 + ".png"
    df = pd.DataFrame({"Risk":[25], "No Effect" : [50], "Gain":[25]}) 
    df.plot(kind='barh', legend = False, stacked=True, color=['#ed713a', '#808080', '#4169e1'])
    plt.axis('off')
    plt.gca().set_axis_off()
    plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, hspace = 0, wspace = 0)
    plt.ylim(None,None)
    plt.autoscale()
    plt.margins(0,0)

    plt.savefig(stimuli_path) # this fails

需要注意的是,将static_url_path参数传递给Flask()调用实际上并没有达到预期的效果,我认为这将为首先查找静态文件的地方建立根,但事实是由于我的/static/目录显然位于根文件夹中,因此该代码仍然无法显示。

否则,就像我说的那样...我需要使用plt.savefig()来接受路径,但仍然无法弄清楚应该如何编写此路径。

在此之前,我设法使静态文件能够正常工作。我不得不将上面对静态文件的两个引用更改为以下内容:

stimuli_path = 'Neuroethics_Behavioral_Task/static/images/stimulus_img' + "1" + ".png"
stim_metadata_path = "Neuroethics_Behavioral_Task/static/textdata/stimulus_data" + str(uid) + ".json"

换句话说,我可以通过在路径中包含根目录来获取静态文件。

至少这使我不满意...直到我尝试将我的应用程序部署到Heroku上。然后我开始收到错误消息,提示Neuroethics_Behavioral_Task/static/images/不是公认的路径...所以现在,我觉得我需要真正开始正确地引用静态文件,并且现在不知道该怎么做。

我已经尝试了变体(例如:images/stimulusimg1.png)并尝试更改了static_url_path参数(例如:static_url_path='/static/),但是这些都导致我的Flask应用程序在本地崩溃,并显示FileNotFound。

我还有另一个重要的后续问题...

此应用程序将在Amazon Mechanical Turk上发布的在线实验中进行。图像应该由我使用的称为JsPsych的框架预先加载。但是像这样的帖子以及我第一次加入的帖子鼓励您使用NGINX What exactly does 'serving static files' mean?

提供文件

我不知道Nginx或wsgi是如何工作的。我是否仍然应该尝试以这种方式提供所有静态文件,如果可以,如何开始?

总而言之,我要问的问题是

  • 我需要将静态文件保存在我的experiment.py /views.py/ apps.py文件中,因此我需要弄清楚实际上表示我的静态图像路径的字符串。我怎么做?我实际上是否需要修改static_url_path变量?
  • 以前为什么我无法成功引用静态文件路径中的根目录
  • 我的图片应该由我使用的JavaScript框架JsPsych预先加载。我仍然应该麻烦设置nginx和wsgi配置吗?
  • 编辑:url_for()也不起作用。

stimuli_in_static = "images/stimulus_img" + "1" + ".png"
stimuli_path = url_for('static', filename=stimuli_in_static)

[这仍然会在.savefig()调用时导致FileNotFound错误,

FileNotFoundError: [Errno 2] No such file or directory: '/static/images/stimulus_img1.png'

类似于这个问题,但是我有一些后续措施。如何在Flask中提供静态文件在适应上一篇文章中的解决方案时,我遇到的主要问题是我需要使用...

python nginx heroku flask static
2个回答
1
投票

根据我的评论,由于Heroku不支持持久性文件系统存储,因此推荐的方法是使用S3。为此,您需要将plot.fig写入Bytes IO缓冲区,然后将其上传到S3。此过程在this SO thread中介绍。


0
投票

考虑烧瓶的文档,了解如何组织烧瓶应用程序。他们谈论的第一个文件结构是“简单模块”模式,第二个文件结构是更复杂的“包”模式。 https://flask.palletsprojects.com/en/1.1.x/tutorial/layout/

© www.soinside.com 2019 - 2024. All rights reserved.