Gunicorn 未加载 Flask 应用密钥

如何解决Gunicorn 未加载 Flask 应用密钥

当我尝试使用 gunicorn -w 3 wsgi:app 运行 Flask 并通过 IP 地址访问页面时,我收到以下错误RuntimeError: A secret key is required to use CSRF. 在终端中。

我不确定是什么导致了这个问题,因为:我在 .env 中设置了一个密钥并且我确认它正在被 Flask 加载,因为当我使用 flask run --host=0.0.0.0 运行应用程序时,然后代码print(app.config['SECRET_KEY']) 将密钥打印到终端。
我想这与 Gunicorn 需要不同的代码来加载密钥有关。

我的 Flask 应用的结构如下:

-denise
--configmodule.py
--__init__.py
--site.db
--models.py
--main
--static
--template
-migrations
-venv
-wsgi.py
-.env

我没有太多设置服务器的经验,以下是相关文件中的代码

__init__.py 文件

from flask import Flask
from flask_sqlalchemy import sqlAlchemy
from denise.configmodule import Config
from flask_bcrypt import Bcrypt
from flask_login import LoginManager
from flask_mail import Mail
from flask_migrate import Migrate
from flask_wtf.csrf import CSRFProtect

db = sqlAlchemy()
bcrypt = Bcrypt()
login_manager = LoginManager()
mail = Mail()
csrf = CSRFProtect()

def create_app():
    app = Flask(__name__)
    app.config.from_object(Config)
    csrf.init_app(app)
    migrate = Migrate(app,db)
    db.init_app(app)
    bcrypt.init_app(app)
    login_manager.init_app(app)
    mail.init_app(app)
    print('SECRET_KEY')
    print(app.config['SECRET_KEY'])
    print('SECRET_KEY')

    #with app.app_context()
    from .main.routes import main

    app.register_blueprint(main)
    return app                                

configmodule.py 文件

from os import environ,path
from dotenv import load_dotenv

basedir = path.abspath(path.dirname(__file__))
load_dotenv(path.join(basedir,'.env'))

class Config(object):
    DEBUG=True
    SECRET_KEY=environ.get('SECRET_KEY')
    sqlALCHEMY_DATABASE_URI='sqlite:///site.db'
    ENV='development'
    MAIL_SERVER = 'smtp.googlemail.com'
    MAIL_PORT = 587
    MAIL_USE_TLS = True
    MAIL_USERNAME = environ.get('EMAIL_USER')
    MAIL_PASSWORD = environ.get('EMAIL_PASS')
    MAIL_DEFAULT_SENDER = environ.get('EMAIL_DEFAULT_SENDER')
    MAIL_MAX_EMAILS = 5
    RECAPTCHA_PUBLIC_KEY = environ.get('RECAPTCHA_PUBLIC')
    RECAPTCHA_PRIVATE_KEY = environ.get('RECAPTCHA_PRIVATE')                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

Wsgi.py 文件


from denise import create_app
from dotenv import load_dotenv

load_dotenv('.env')

app = create_app()

if __name__ == "__main__":
    app.run()

.env 文件

SECRET_KEY='hiiii17011b97b7ed4aeb9ae7f75a0b66a006c8efd4ab0759e5d2'
EMAIL_USER='email@email.email'
EMAIL_DEFAULT_SENDER='email@email.email'
EMAIL_PASS='password'
RECAPTCHA_PUBLIC='randomstringofletter'
RECAPTCHA_PRIVATE='lalalalalal'                                                                  

我尝试了 Corey Schafer 和 Pretty Printed 的一些关于将 Flask 应用程序部署到生产环境的教程。我想我在某处错过了一些东西。

解决方法

(用手机写的)

看看你的 wsgi 文件:

  1. 首先导入 create_app,它会转到您的 __init__ 文件
  2. __init__ 文件导入 Config,它不是延迟初始化,而是在导入时(我会更改此设置,但这不是问题)
  3. 在配置文件中取__file__的目录名,即denise,然后用.env加入它,而denise目录中没有env文件

关于运行flask run调试,我不使用flask,但它可能只是不使用wsgi文件。

,

很好的旧垃圾邮件打印语句来救援。

注意,我使用 gunicorn -w 1 -t 1 wsgi:app 来确保单个工作线程和线程,否则控制台会收到来自多个来源的 print 语句的垃圾邮件。

导入和加载订单可能是罪魁祸首。 load_dotenv(path.join(basedir,'.env')) 中的语句 configmodule.py 也存在问题。它在目录 .env 中查找 denise 文件并无提示地失败。

我制作了一个可重现的例子,见下文。

解决方法是:

  • 在从 load_dotenv('.env') 导入任何内容之前先在 wsgi.py 中执行 denise
  • 将您在 configmodule.py 中的加载方式更改为 load_dotenv(path.join(basedir,'../.env')),但由于您使用了应用程序工厂模式结构,我不确定这是否可取。这可能会导致未来出现不良行为。

configmodule.py

​​>
from os import environ,path
from dotenv import load_dotenv,dotenv_values
from pprint import pprint


print('--------------------------------------------------------------------------------------------------------------------------------')
print('configmodule')
print('--------------------------------------------------------------------------------------------------------------------------------')


basedir = path.abspath(path.dirname(__file__))
load_dotenv(path.join(basedir,'.env'))
try:
    with open(path.join(basedir,'.env')) as infile:
        for line in infile:
            print(line)
except:
    print('=========================== FILENOTFOUND')


class Config(object):
    print('--------------------------------------------------------------------------------------------------------------------------------')
    print('configmodule:Config')
    print('--------------------------------------------------------------------------------------------------------------------------------')
    pprint(dotenv_values(path.join(basedir,'.env')))
    print('--------------------------------------------------------------------------------------------------------------------------------')
    pprint(environ)
    DEBUG=True
    SECRET_KEY=environ.get('SECRET_KEY')
    SQLALCHEMY_DATABASE_URI='sqlite:///site.db'
    ENV='development'
    MAIL_SERVER = 'smtp.googlemail.com'
    MAIL_PORT = 587
    MAIL_USE_TLS = True
    MAIL_USERNAME = environ.get('EMAIL_USER')
    MAIL_PASSWORD = environ.get('EMAIL_PASS')
    MAIL_DEFAULT_SENDER = environ.get('EMAIL_DEFAULT_SENDER')
    MAIL_MAX_EMAILS = 5
    RECAPTCHA_PUBLIC_KEY = environ.get('RECAPTCHA_PUBLIC')
    RECAPTCHA_PRIVATE_KEY = environ.get('RECAPTCHA_PRIVATE')

wsgi.py

​​>
from os import environ
from denise import create_app
from dotenv import load_dotenv,dotenv_values


print('--------------------------------------------------------------------------------------------------------------------------------')
print('WSGI')
print('--------------------------------------------------------------------------------------------------------------------------------')
load_dotenv('.env')
print(dotenv_values('.env'))
print('--------------------------------------------------------------------------------------------------------------------------------')
with open('.env') as infile:
    print(infile.readlines())
print('--------------------------------------------------------------------------------------------------------------------------------')
print(environ)
print('--------------------------------------------------------------------------------------------------------------------------------')

app = create_app()

if __name__ == "__main__":
    app.run()

我建议修改 wsgi.py 以防止未来出现问题,如上所述,尽管这可能违反 PEP8 标准。

固定的 wsgi.py

​​>
from dotenv import load_dotenv
load_dotenv('.env')

from denise import create_app


app = create_app()

if __name__ == "__main__":
    app.run()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?