使用临时环境变量运行 Python 脚本

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)

之后,它不会返回任何内容。环境变量只是临时设置的,就像您所需要的那样。


jsb*_*eno 3

您将需要一个“加载器”小程序,它将使用适当的变量调用第二个程序。当然,用 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)