Почему Flask не настраивает определенные переменные среды из класса config? Нужна помощь в понимании процесса настройки - PullRequest
1 голос
/ 28 января 2020

Мое приложение, по-видимому, вполне способно конфигурировать на основе файла .env, импортированных классов конфигурации и непосредственного определения переменных. Однако FLASK_DEBUG не может измениться в зависимости от того, как я определяю переменные.

Я, вероятно, должен отметить, что я использую код Visual Studio на windows. Мне сказали, что мне нужно использовать Linux или что-то еще, кроме windows, и я собираюсь это сделать, но сейчас это не вариант, поэтому любая помощь в понимании того, как это работает с системой, которая у меня есть, и как с ней обращаться, очень ценим.

config.py:

import os
basedir = os.path.abspath(os.path.dirname(__file__))

class DevelopmentConfig(object):
    os.environ['SECRET_KEY'] = b'something'
    os.environ['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URL') or \
        'sqlite:///' + os.path.join(basedir, 'app.db')
    os.environ['SQLALCHEMY_TRACK_MODIFICATIONS'] = 'False'
    os.environ['FLASK_DEBUG'] = '1'
    os.environ['DEV_DICT'] = 'dev_config_class_environ_dictionary_activated_and_working'

class ProductionConfig(object):
    os.environ['SECRET_KEY'] = os.environ.get('SECRET_KEY')
    os.environ['SQLALCHEMY_DATABASE_URI'] = os.environ.get('PRODUCTION_DATABASE_URI')
    os.environ['SQLALCHEMY_TRACK_MODIFICATION'] = 'False'
    os.environ['FLASK_DEBUG'] = '0'
    os.environ['PROD_DICT'] = 'prod_config_class_environ_dictionary_activated_and_working'

init.py:

from flask import Flask
from config import DevelopmentConfig, ProductionConfig
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from dotenv import load_dotenv, find_dotenv
import os

app = Flask(__name__)
db = SQLAlchemy(app)
migrate = Migrate(app, db)

load_dotenv(find_dotenv())

if os.environ.get('FLASK_ENV') == 'development':
    print("Environment is development")
    app.config.from_object(DevelopmentConfig)
elif os.environ.get('FLASK_ENV') == 'production':
    print("Environment is production")
    app.config.from_object(ProductionConfig)

print(os.environ.get('TEST_DOTENV'))   #This value is stored in .env
print(os.environ.get('DEV_DICT'))      #defined in class DevelopmentConfig as os.environ['DEV_DIVT']
print(os.environ.get('PROD_DICT'))     #same but in the ProductionConfig class
print(os.environ.get('FLASK_ENV'))     #defined differently in both classes and CONFIGS CORRECTLY
print(os.environ.get('FLASK_DEBUG'))   #defined differently in both classes and DOES NOT CONFIG CORRECTLY

.env:

FLASK_ENV=development
FLASK_APP=run.py
SECRET_KEY=b'something'
PRODUCTION_DATABASE_URI='something_else'
TEST_DOTENV=config_from_dotenv_is_working   #prints correctly to command line, as do other variables defined here

Когда я запустите приложение:

(flaskvenv) PS C:\Users\peter\Desktop\Projects\Social Work Site\sw_app> flask run
 * Serving Flask app "run.py" (lazy loading)
 * Environment: development
 * Debug mode: on
 * Restarting with stat
c:\...__init__.py:814: UserWarning: Neither SQLALCHEMY_DATABASE_URI nor SQLALCHEMY_BINDS is set. Defaulting SQLALCHEMY_DATABASE_URI to "sqlite:///:memory:".
  'Neither SQLALCHEMY_DATABASE_URI nor SQLALCHEMY_BINDS is set. '
c:\...__init__.py:835: FSADeprecationWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead... 

Environment is development                                     #changes correctly if I change it in .env
config_from_dotenv_is_working                                  #further proof .env works fine
dev_config_class_environ_dictionary_activated_and_working      #prints regardless of which class gets called
prod_config_class_environ_dictionary_activated_and_working     #also prints regardless of which class gets called
development                                                    #changes to production properly if I change it in .env
0                                       #stubbornly stays set to 0 regardless of it being set in config

 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

Вот странная часть:

Когда я определил FLASK_DEBUG в файле .env, командная строка правильно отображает его в выводе c например, как * Debug mode: off или * Debug mode: on в зависимости от того, установлю ли я его на 0 или 1 соответственно.

НО, когда я вызываю его с os.environ.get('FLASK_DEBUG'), он отображается как 0 независимо от того, что я do.

Исходя из этого, у меня есть несколько вопросов.

Основной вопрос и, конечно, суть проблемы:

  1. Почему Flask не настраивается FLASK_DEBUG, но другие переменные настраиваются нормально?

Другие вопросы, которые, как я подозреваю, могут иметь какое-то соединение и могут помогите мне понять это:

Какую роль играет Windows ОС в этой проблеме? Почему оба класса конфигурации конфигурируют переменные среды, если я вызываю только одну из них? Почему, если автомат c вывод говорит мне, что Debug mode это on делает os.environ.get('FLASK_DEBUG') все еще возвращает 0?

Я могу решить это, определив FLASK_ENV в .env, но я хочу чтобы понять, как это работает. Несоответствие в том, как все происходит, заставляет меня чувствовать себя неловко, когда я не знаю, как и почему вещи функционируют так, как они работают.

Заранее спасибо!

1 Ответ

1 голос
/ 28 января 2020

Вы смешиваете понятия классов конфигурации и переменных среды.

Объяснение своего результата

Если вы определите два класса и сразу в этих определениях установите переменные среды, они оба будут Беги немедленно. Не делайте этого:

# config.py
import os

class DevelopmentConfig(object):
    os.environ['FLASK_DEBUG'] = '1'

class ProductionConfig(object):
    os.environ['FLASK_DEBUG'] = '0'

print('FLASK_DEBUG is', os.environ['FLASK_DEBUG'])

После запуска этого кода оба класса установят env. переменная, и так как 0 является последним значением, которое будет установлено, результат будет 0:

$ python config.py
FLASK_DEBUG is 0

По этой причине ваш FLASK_DEBUG всегда равен 0. Весь ваш код внутри DevelopmentConfig и ProductionConfig запускается независимо от того, что установлено в вашем файле .env. Ваша проблема не связана с Windows.

Помимо классов, вы также устанавливаете переменные окружения из файла .env, включая FLASK_ENV=development. Это переменная, распознаваемая Flask, которая включит режим отладки. Это причина, по которой режим отладки включен в Flask.

Одно решение: использовать спецификацию среды c config config

Определить значения в классах:

class DevelopmentConfig(object):
    MY_VARIABLE = 'dev value'
    ...

class ProductionConfig(object):
    MY_VARIABLE = 'prod value'
    ...

Тогда установить окружение в переменной окружения. Это можно сделать непосредственно в ОС, или вы можете использовать файл .env, если вам нравится:

FLASK_ENV=development

На рабочем сервере вы должны создать другой файл .env:

FLASK_ENV=production

Затем загрузите соответствующий класс в Flask:

from dotenv import load_dotenv, find_dotenv
from flask import Flask
import os

load_dotenv(find_dotenv())    
app = Flask(__name__)
config = ProductionConfig() if os.environ.get('FLASK_ENV') == 'production' else DevelopmentConfig()
app.config.from_object(config)
print(app.config['MY_VARIABLE'])

В этом случае вам даже не нужно устанавливать FLASK_DEBUG, потому что Flask установит его автоматически на основе FLASK_ENV.

Другие решения

Вы также можете полностью отказаться от классов конфигурации и вместо этого импортировать все значения из переменных среды или из файлов конфигурации. Прочитайте Flask руководство по настройке для более подробной информации.

...