【问题标题】:set environment variables by file using python使用python通过文件设置环境变量
【发布时间】:2017-05-12 09:16:38
【问题描述】:

我有一个文件包含一组环境变量。

env_script.env:

export a=hjk
export b=jkjk
export c=kjjhh
export i=jkkl
..........

我想通过读取文件来设置这些环境变量。 我如何在 python 中做到这一点

尝试过的示例代码:

pipe = subprocess.Popen([".%s;env", "/home/user/env_script.env"], stdout=subprocess.PIPE, shell=True)
output = pipe.communicate()[0]
env = dict((line.split("=", 1) for line in output.splitlines()))
os.environ.update(env)

请给点建议

【问题讨论】:

    标签: python linux shell


    【解决方案1】:

    有一个很棒的 python 库python-dotenv,它允许您将变量从.env 文件或您想要的任何文件导出到您的环境,您可以将其排除在源代码控制之外(即添加到.gitignore ):

    # to install
    pip install -U python-dotenv
    
    # your .env file
    export MY_VAR_A=super-secret-value
    export MY_VAR_B=other-very-secret-value
    ...
    

    当你开始时你只需在 python 中加载它:

    # settings.py
    from dotenv import load_dotenv
    load_dotenv()
    

    然后,您可以稍后在代码中访问任何变量:

    from os import environ
    
    my_value_a = environ.get('MY_VALUE_A')
    print(my_value_a) # 'super-secret-value'
    

    【讨论】:

      【解决方案2】:

      您不需要使用子流程。

      读取行并拆分环境变量名称,值并将其分配给os.environ

      import os
      
      with open('/home/user/env_script.env') as f:
          for line in f:
              if 'export' not in line:
                  continue
              if line.startswith('#'):
                  continue
              # Remove leading `export `
              # then, split name / value pair
              key, value = line.replace('export ', '', 1).strip().split('=', 1)
              os.environ[key] = value
      

      或使用dict.updategenerator expression

      with open('env_script.env') as f:
          os.environ.update(
              line.replace('export ', '', 1).strip().split('=', 1) for line in f
              if 'export' in line
          )
      

      或者,您可以制作一个包装器 shell 脚本,sources 和 env_script.env,然后执行原始 python 文件。

      #!/bin/bash
      source /home/user/env_script.env
      python /path/to/original_script.py
      

      【讨论】:

      • 我在使用第一个方法键时遇到此错误,value = line.replace('export ', '', 1).split('=', 1) ValueError: need more than 1 value解包
      • @user092,感谢您的反馈。似乎有一条线没有export ...。我更新了答案以跳过这些行。请尝试更新后的代码。
      • 环境变量在系统中没有更新。没有变化
      • @user092, 你想改变 shell 的环境变量吗?更新进程本身的环境变量是可能的。更改的环境变量可以继承给子进程。但是,无法更新父进程的环境变量。
      • @user092,只需在 shell 中运行 source /home/user/env_script.env
      【解决方案3】:

      现代操作系统不允许子进程改变其父进程的环境。只能为当前进程及其后代更改环境。 Python 解释器是调用 shell 的子代。

      这就是为什么source 不是外部命令而是由shell 直接解释以允许更改其环境的原因。

      它曾经可以在具有 .COM 可执行格式的老式 MS/DOS 系统中实现。 .com 可执行文件有一个 256 (0x100) 字节的前导码,其中有一个指向 COMMAND.COM 环境字符串的指针!因此,对于低级内存功能,在确保不覆盖环境之外的任何内容后,命令可以直接更改其父环境。

      在现代操作系统中可能仍然可以,但需要系统的配合。例如,如果设置了适当的权限,Windows 可以允许一个进程对另一个进程的内存进行读/写访问。但这确实是一种 hacky 方式,我不敢在 Python 中这样做。

      TL/DR:如果您的要求是从 Python 脚本更改 calling shell 的环境,那么您误解了您的要求。


      但简单的方法是使用修改后的环境启动一个新的 shell:

      import os
      import subprocess
      
      env = os.environ.copy() # get a copy of current environment
      # modify the copy of environment at will using for example falsetru's answer
      # here is just an example
      env['AAA'] = 'BBB'
      # and open a subshell with the modified environment
      p = subprocess.Popen("/bin/sh", env = env)
      p.wait()
      

      【讨论】:

      • 有趣,但这个答案完全是题外话,它没有回答原帖中的问题
      猜你喜欢
      • 1970-01-01
      • 2016-12-23
      • 1970-01-01
      • 2020-04-05
      • 1970-01-01
      • 2015-05-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多