如何使用 package.json 调用设置环境变量并让其他脚本和命令可以访问这些变量的脚本

Posted

技术标签:

【中文标题】如何使用 package.json 调用设置环境变量并让其他脚本和命令可以访问这些变量的脚本【英文标题】:how to use package.json to call a script that sets environment variables and have those variables accessible to other scripts and commands 【发布时间】:2020-04-13 19:47:20 【问题描述】:

我有一个cookiecutter Flask 应用程序。我正在尝试修改我的 package.json,以便命令 npm start 使用 Python 脚本设置一些环境变量。

现在我的 Python 脚本似乎运行正常,但是当 package.json 执行启动 Flask 的脚本时,没有设置环境变量。

我可以开始阐明可能导致问题的原因。我的 Python 脚本可能在与 Flask 不同的进程中运行,并且正在其自己的进程中设置环境变量,但 Flask 无法访问它们。我需要做一些类似的采购我的 .bashrc。但我不知道那个类比是什么。或者问题可能完全不同!

这是我package.json的一部分:

"scripts": 
"build": "NODE_ENV=production webpack --progress --colors -p",
"start": "npm run set-trusted-vars-no-force && npm run start-servers",
"start-local": "npm run set-local-vars && npm start",
"start-servers": "concurrently -n \"WEBPACK,FLASK\" -c \"bgBlue.bold,bgMagenta.bold\" \"npm run webpack-dev-server\" \"npm run flask-server\"",
"webpack-dev-server": "NODE_ENV=debug webpack-dev-server --port 8081 --hot --inline $PUBLIC",
"flask-server": "flask run",
"lint": "eslint \"assets/js/*.js\"",
"set-trusted-vars": "python ../config/set_env_vars.py --reset T --env trusted --credentials ../config/credentials/secrets.yml --config ../config/config.yml",
"set-trusted-vars-no-force": "python ../config/set_dev_env_vars.py --env trusted --credentials ../config/credentials/secrets.yml --config ../config/config.yml",
"set-local-vars": "python ../config/set_dev_env_vars.py --reset T'",
"set-local-vars-no-force": "python ../config/set_dev_env_vars.py"

这是set_dev_env_vars.py 的一小部分相关内容:

def set_config(config_path, config_name):
    with open(config_path) as file:
        configs = yaml.safe_load(file)
        config = configs[config_name]
        for var in config:
            os.environ[var] = str(config[var])
            print(var, os.environ[var])

打印出来的内容如下:

ENV local
FLASK_APP autoapp.py
FLASK_ENV development
SECRET_KEY not-so-secret
FLASK_RUN_PORT 8000
FLASK_RUN_HOST 0.0.0.0

Flask 最终会抱怨:

[FLASK] Error: Could not locate a Flask application. You did not provide the "FLASK_APP" environment variable, and a "wsgi.py" or "app.py" module was not found in the current directory.
[FLASK] npm ERR! code ELIFECYCLE
[FLASK] npm ERR! errno 2
[FLASK] npm ERR! cookiecutter_mbam@1.0.0 flask-server: `flask run`
[FLASK] npm ERR! Exit status 2

设置环境变量以便 Flask 可以找到它们的正确方法是什么?

附言我知道在没有其他上下文的情况下,这似乎是设置环境变量的过度设计的解决方案,但我也在处理更复杂的情况,这些情况在这里不可见。

【问题讨论】:

" 我的 Python 脚本可能在与 Flask 不同的进程中运行,..." 是的,这是核心问题。通常的解决方案是让 python 进程将环境变量写入标准输出。然后调用进程捕获该输出并使用它在其地址空间中设置变量。我不知道 Flask,所以我不能告诉你如何安排它来做到这一点。是什么让您认为 set-trusted-vars 很特别并导致您的 python 程序运行?谷歌表示,这恰好出现在两个文件中;其中之一就是这个问题。你读过flask.palletsprojects.com/en/1.1.x/config吗? set-trusted-vars 是我对scripts 的补充。其实现在看肯定是从来没有运行过,因为我忘记更新Python脚本的名字了,但是运行的是set-trusted-vars-no-forcenpm start 导致它运行,这就是调用 set_dev_env_vars.py 的原因。是的,我已经阅读了 Flask 的配置文档。 Flask 文档与这个问题无关。在内部,Flask 应用程序将读取环境变量。我的问题实际上是关于设置环境变量。 【参考方案1】:

我的 Python 脚本可能在与 Flask 不同的进程中运行,并且正在其自己的进程中设置环境变量,但 Flask 无法访问它们。

使用os.environ['FOO']='bar' 设置环境变量会将它们设置为进程或其子进程(see this answer) 的持续时间。 Other threads 不鼓励尝试让 Python 在全局范围内设置它们,以及一些 hacky 解决方案。

不仅如此,如果set_dev_env_vars.py 确实设置了全局环境变量,这会将前端绑定到与 Flask 服务器相同的机器上。将这两者分开是标准程序。我很好奇您是否有理由从前端启动后端服务器?这是 flask-cookiecutter 的行为还是你自己实现的(或被卡住了?)

大概config.yml 也包含前端配置。也许您应该从那里分离与烧瓶相关的配置值并将它们写入.env 文件并使用python-dotenv 将它们加载到您的Flask 应用程序中。您甚至可以使用dot-env (javascript) 让前端加载其配置。

有了这种分离,您就可以将前端与后端分开部署,只需确保所需的 .env 文件可用于相应的服务器。

【讨论】:

感谢您的回答!我确实从 cookiecutter 继承了这个方案,但如果我能提出一个很好的理由来摆脱它,我不会坚持任何事情,而且我以前没有考虑过这种可能性。如果我制作一个负责编排的 Python 脚本,我可以将设置环境变量的进程设为父进程。或者我可能只是写信给 .env ——我有兴趣找到另一种方法,以便可以在实际环境中设置一组更标准的变量,然后单个开发人员可以使用 .env 进行瞬态或特殊覆盖。 我想避免使用 .env 的另一个原因是某些环境变量将成为其他应用程序的凭据,我认为如果它们从未写入文件会更安全。 即使我保留npm start 作为启动应用程序的方法,我仍然可以更改它调用的脚本,以便flask run 获得一个设置环境变量的父级(无论是因为那个父级已将它们接受到标准输入或已自行确定。

以上是关于如何使用 package.json 调用设置环境变量并让其他脚本和命令可以访问这些变量的脚本的主要内容,如果未能解决你的问题,请参考以下文章

windows package.json设置多个环境变量

json 初学者package.json文件 - 下载文件 - 设置appname和版本属性 - 调用npm install-开始工作!

json 初学者package.json文件 - 下载文件 - 设置appname和版本属性 - 调用npm install-开始工作!

如何给现有工程初始化一个react-native环境的package.json

如何使用 package.json 运行 ts 脚本?

如何在 NodeJs 中更改 package.json 中的主文件