我有一个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
因此,当应用程序被 Docker 化并在 Kubernetes 农场上运行时,这很好。
但是,当在没有Docker和Kubernetes的本地机器上运行应用程序时,只有一个不起眼的命令:
python app.py
我必须让 Python 模块找到带有os.getenv('var1')
的环境变量,即使没有 ConfigMap 或 Pod。
是否可以在不需要在 Python 模块中添加额外代码或向本地机器系统添加环境变量的情况下?
在 shell 中,您也可以在调用脚本之前临时分配环境变量的值。根本不需要更改脚本。
考虑以下app.py
,它只打印环境变量ENV_PARAM
和ENV_PARAM2
:
#!/usr/bin/env python3
import os
print(os.environ['ENV_PARAM'])
print(os.environ['ENV_PARAM2'])
当变量未设置并且您像这样称呼它时
python app.py
你会得到一个KeyError
.
密钥错误:"ENV_PARAM">
当您在同一行中指定值并像这样调用它时
ENV_PARAM='foo' ENV_PARAM2='bar' python app.py
它工作正常。输出:
foo
bar
这不会设置超出此范围的环境变量,因此如果您这样做
echo "$ENV_PARAM"
之后,它将不返回任何内容。环境变量只是临时设置的,就像您需要的那样。
你需要有一个"加载器"小程序,它将使用适当的变量调用第二个程序。 当然,在 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)
(当然,您需要安装一些第三方库才能读取yaml配置文件-我已经使用PyYAML
来测试这一点)
如果你将上面的脚本标记为可执行,你可以直接在命令行中使用它,而不用前缀"python3"——否则,如果你把这个文件命名为"runner.py",你的命令行可以是
python3 runner.py myconfig.yaml myscript.py parameter1 parameter2 parameter3
如果您需要传递当前环境并使用脚本中的变量进行更新,请在.run
调用之前执行此操作:
import os
...
config = yaml.load(...)[...]
config = {**os.environ, **config}
另外,看到这将使用它正在运行的相同 Python 解释器来执行脚本,或多或少幼稚的方式(只需检查字面上的".py"文件扩展名) - 如果您需要它更健壮,建议在目标脚本上执行 stat 并检查它是否可执行 - 然后直接调用它 - 并且仅将当前的 Python 解释器用于其他文件。
或修改您的代码
由于您有一个脚本作为入口点,并且希望简化 3rdy paties 的运行,因此您可以更改它而不是使用通用加载器 - 在这种情况下,我会重新评论添加一个额外的配置变量只是为了表明变量已经正确设置 - 所以当脚本在其容器中运行时,它什么都不做 - 否则,它会如上所述加载数据,并更新其 os.envrion。
换句话说,在代码的入口点,执行一些操作:
if not os.environ.get("EVERYTHING_SETUP"):
import yaml
config = yaml.load(open("myconfig.yaml"))["data"]
os.environ.update(config)
您可以通过在模块的environ
字典中添加键值对来设置预期的环境变量os
该变量。
import os
os.environ['intended var'] = 'intended value'
示例运行
>>> os.getenv('intended var')
'intended value'