Я испытываю очень странное поведение, в котором я не могу разобраться, и это сводит меня с ума.
Я запускаю приложение flask локально, используя цель make
. Команда, которую он запускает, следующая:
export FLASK_APP=foodbank_southlondon.launch:main FBSL_ENVIRONMENT=dev FLASK_ENV=development && \
. $(_VENV_ACTIVATE) && \
flask run
Вот содержимое launch.py
:
import logging
import os
import dotenv
from foodbank_southlondon import api, app, bff, config, oauth
from foodbank_southlondon.api import events, lists, requests
import foodbank_southlondon.views # noqa: F401
import foodbank_southlondon.errors # noqa: F401
import foodbank_southlondon.api.errors # noqa: F401
import foodbank_southlondon.api.events.views # noqa: F401
import foodbank_southlondon.api.lists.views # noqa: F401
import foodbank_southlondon.api.requests.views # noqa: F401
import foodbank_southlondon.bff.views # noqa: F401
# ENVIRONMENT VARIABLES
_FBSL_ENVIRONMENT_ENV_VAR = "FBSL_ENVIRONMENT"
def main():
environment = os.environ.get(_FBSL_ENVIRONMENT_ENV_VAR)
app.logger.setLevel(logging.INFO if environment == "prod" else logging.DEBUG)
env_file_path = os.path.join(app.root_path, "..", f"{environment}.env")
app.logger.info(f"Loading .env file, {env_file_path}...")
dotenv.load_dotenv(env_file_path)
app.logger.info(f"Loading environment, {environment} ...")
app.config.from_object(config.CONFIGURATIONS[environment])
app.logger.info(f"Initialising APIs, OAuth, attaching namespaces and registering blueprints ...")
oauth.register(name="google", server_metadata_url="https://accounts.google.com/.well-known/openid-configuration",
client_kwargs={"scope": "openid email profile"})
oauth.init_app(app)
api.rest.init_app(api.blueprint)
api.rest.add_namespace(events.namespace)
api.rest.add_namespace(lists.namespace)
api.rest.add_namespace(requests.namespace)
app.register_blueprint(api.blueprint, url_prefix="/api")
bff.rest.init_app(bff.blueprint)
app.register_blueprint(bff.blueprint, url_prefix="/bff")
return app
Вот сокращенное содержимое config.py
, важно отметить в том, что мой класс конфигурации dev наследуется от базового класса, а базовый класс - единственное место, которое определяет GOOGLE_CLIENT_SECRET и происходит от os.environ.get:
import os
class _Config(object):
...
GOOGLE_CLIENT_SECRET = os.environ.get("FBSL_CLIENT_SECRET")
...
class DevelopmentConfig(_Config):
... # i don't set GOOGLE_CLIENT_SECRET here
class ProductionConfig(_Config):
...
CONFIGURATIONS = {
"dev": DevelopmentConfig,
"prod": ProductionConfig
}
Внутри dev.env
:
FBSL_CLIENT_SECRET = secret
FBSL_SA_KEY = secret
Дополнительный контекст
Мой бэкэнд обслуживает реакцию SPA как набор файлов c stati. Когда пользователь попадает на мой веб-сайт, например, маршрут localhost: 5000 / my flask немедленно перенаправляет его на вход в Google (используя authlib
). Google отправляет их обратно в мой обратный вызов / auth, и если у них есть разрешение на мой сайт, я затем перенаправляю их обратно в /, но на этот раз я обслуживаю их файлы stati c, а не перенаправляю их для входа в систему. Authlib требует, чтобы переменная конфигурации приложения GOOGLE_CLIENT_SECRET
была настроена, чтобы иметь возможность авторизовать их с помощью Google.
ПРОБЛЕМА
При первом запуске сервера сервер запускается нормально, я вижу сообщения журнала, которые показывают, что выполняется dev.env. Типичный двойной вывод, который вы получаете, когда включен режим отладки:
export FLASK_APP=foodbank_southlondon.launch:main FBSL_ENVIRONMENT=dev FLASK_ENV=development && \
. .venv/bin/activate && \
flask run
* Serving Flask app "foodbank_southlondon.launch:main" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 277-037-026
[2020-05-08 09:21:50,778] INFO in launch: Loading .env file, /home/ac/Projects/Home/foodbank-southlondon/backend/foodbank_southlondon/../dev.env...
[2020-05-08 09:21:50,779] INFO in launch: Loading environment, dev ...
[2020-05-08 09:21:50,779] INFO in launch: Initialising APIs, OAuth, attaching namespaces and registering blueprints ...
[2020-05-08 09:21:50,919] INFO in launch: Loading .env file, /home/ac/Projects/Home/foodbank-southlondon/backend/foodbank_southlondon/../dev.env...
[2020-05-08 09:21:50,919] INFO in launch: Loading environment, dev ...
[2020-05-08 09:21:50,920] INFO in launch: Initialising APIs, OAuth, attaching namespaces and registering blueprints ...
Я могу посетить localhost: 5000, и меня перенаправляют на вход, я вхожу в систему и вижу веб-сайт.
Если Затем я останавливаю свой веб-сервер и запускаю его снова в ТОЧНО таким же образом, я вижу тот же вывод терминала EXACT . Если я затем перейду на localhost: 5000, я увижу эту ошибку вместе с ее трассировкой в отладчике:
authlib.integrations.base_client.errors.OAuthError
authlib.integrations.base_client.errors.OAuthError: invalid_request: client_secret is missing.
Если я нажму на отладчик, открою интерактивную оболочку и наберу:
from foodbank_southlondon import app
print(app.config)
Я вижу все переменные конфигурации, и ВСЕ установлено, как ожидалось, кроме двух переменных конфигурации, которые я загружаю с помощью os.environ.get, они обе равны Нет.
Чтобы я мог исправить эта безумная проблема, мне нужно что-то сделать с config.py, чтобы "изменить" его. Например, если я напишу print(GOOGLE_CLIENT_SECRET)
прямо под тем местом, где он определен, я не только увижу этот вывод, который не является значением None, но и сам факт моего введения оператора печати исправит его! Но затем, если я остановлю сервер и запустю его снова, у меня снова возникнет та же проблема, и мне нужно будет каким-то образом изменить файл.
Заключительный момент: Если я не остановлю сервер и позволю перезагрузке просто перезагрузиться, я избежу этой проблемы.
Я предполагаю, что выиграл ' Я сталкиваюсь с этой проблемой в производственной среде, но это делает разработку настолько болезненной, и это просто безумная проблема. Это как если бы у меня возникла какая-то странная проблема с кешированием переменных среды между остановкой и запуском сервера. Я понятия не имею. Пожалуйста, помогите!