vah*_*det 8 python environment-variables
我有一个 Python 应用程序,它利用 Kubernetes 配置中的环境变量,例如:
apiVersion: v1
kind: ConfigMap
metadata:
name: my-config
namespace: default
data:
var1: foo
var2: bar
---
apiVersion: v1
kind: Pod
metadata:
name: my-pod
namespace: default
spec:
containers:
- envFrom:
- configMapRef:
name: my-config
Run Code Online (Sandbox Code Playgroud)
因此,当应用程序被 Docker 化并在 Kubernetes 场上运行时,这很好。
但是,当在没有 Docker 和 Kubernetes的本地机器上运行应用程序时,只有一个不起眼的命令:
apiVersion: v1
kind: ConfigMap
metadata:
name: my-config
namespace: default
data:
var1: foo
var2: bar
---
apiVersion: v1
kind: Pod
metadata:
name: my-pod
namespace: default
spec:
containers:
- envFrom:
- configMapRef:
name: my-config
Run Code Online (Sandbox Code Playgroud)
os.getenv('var1')即使没有 ConfigMap 或 Pod,我也必须让 Python 模块找到环境变量。
是否可以不需要在 Python 模块中添加额外的代码或向本地机器系统添加环境变量?
bud*_*mat 15
在 shell 中,您还可以在调用脚本之前临时为环境变量分配值。根本不需要改变你的脚本。
考虑以下app.py仅打印环境变量ENV_PARAM和ENV_PARAM2:
#!/usr/bin/env python3
import os
print(os.environ['ENV_PARAM'])
print(os.environ['ENV_PARAM2'])
Run Code Online (Sandbox Code Playgroud)
当变量没有设置并且你这样调用它时
python app.py
Run Code Online (Sandbox Code Playgroud)
你会得到一个KeyError.
关键错误:“ENV_PARAM”
当您在同一行中指定值并像这样调用它时
ENV_PARAM='foo' ENV_PARAM2='bar' python app.py
Run Code Online (Sandbox Code Playgroud)
效果很好。输出:
foo
bar
Run Code Online (Sandbox Code Playgroud)
这不会设置超出该范围的环境变量,所以如果你这样做
foo
bar
Run Code Online (Sandbox Code Playgroud)
之后,它不会返回任何内容。环境变量只是临时设置的,就像您所需要的那样。
您将需要一个“加载器”小程序,它将使用适当的变量调用第二个程序。当然,用 Python 也更方便,因为一切都已经设置好了 - 但它可能是一些东西
#!/usr/bin/env python3
import subprocess
import sys
import yaml
config = yaml.load(open(sys.argv[1]))["data"]
# Instead of "data" here, use the yaml path to the place in the configuration your variables are
cmdline = sys.argv[2:]
if cmdline[0].endswith(".py"):
cmdline.insert(0, sys.executable)
result = subprocess.run(cmdline, env=config)
exit(result.returncode)
Run Code Online (Sandbox Code Playgroud)
(当然,您需要安装一些第三方库才能读取 yaml 配置文件 - 我曾经PyYAML测试过这一点)
如果将上述脚本标记为可执行,则可以直接在命令行中使用它,而无需添加前缀“python3” - 否则,如果将此文件命名为“runner.py”,则命令行可以是
python3 runner.py myconfig.yaml myscript.py parameter1 parameter2 parameter3
Run Code Online (Sandbox Code Playgroud)
如果您需要传递当前环境并仅使用脚本中的变量进行更新,请在调用之前执行此操作.run:
import os
...
config = yaml.load(...)[...]
config = {**os.environ, **config}
Run Code Online (Sandbox Code Playgroud)
另外,请注意,这将使用运行它的相同 Python 解释器来执行脚本,以一种或多或少天真的方式(仅检查文字“.py”文件扩展名) - 如果您需要它更强大,它建议对目标脚本执行 stat 并检查它是否可执行 - 然后直接调用它 - 并且仅对其他文件使用当前的 Python 解释器。
由于您有一个脚本作为入口点,并且希望简化第三个馅饼的运行,因此您可以更改它而不是使用通用加载程序 - 在这种情况下,我建议添加一个额外的配置变量只是为了指示变量是已经正确设置 - 因此当脚本在其容器中运行时,它不会执行任何操作 - 否则,它会按上述方式加载数据,并更新其 os.envrion。
换句话说,在代码的入口点,执行以下操作:
if not os.environ.get("EVERYTHING_SETUP"):
import yaml
config = yaml.load(open("myconfig.yaml"))["data"]
os.environ.update(config)
Run Code Online (Sandbox Code Playgroud)