12

I have a file contains set of environment variables .

env_script.env:

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

I want set these environment variables by reading from file . how can i do this in python

Tried sample code:

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)

Please give some suggestion

user092
  • 437
  • 2
  • 10
  • 26

3 Answers3

12

There's a great python library python-dotenv that allows you to have your variables exported to your environment from a .env file, or any file you want, which you can keep out of source control (i.e. add to .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
...

And you just load it in python when your start like:

# settings.py
from dotenv import load_dotenv
load_dotenv()

Then, you can access any variable later in your code:

from os import environ

my_value_a = environ.get('MY_VALUE_A')
print(my_value_a) # 'super-secret-value'
juanesarango
  • 560
  • 9
  • 17
10

You don't need to use subprocess.

Read lines and split environment variable name, value and assign it to 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

or using dict.update and generator 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
    )

Alternatively, you can make a wrapper shell script, which sources the env_script.env, then execute the original python file.

#!/bin/bash
source /home/user/env_script.env
python /path/to/original_script.py
radtek
  • 34,210
  • 11
  • 144
  • 111
falsetru
  • 357,413
  • 63
  • 732
  • 636
  • i am getting this error while using first method key, value = line.replace('export ', '', 1).split('=', 1) ValueError: need more than 1 value to unpack – user092 May 12 '17 at 09:30
  • @user092, Thank you for the feedback. It seems like there's a line without `export ...`. I updated the answer to skip such lines. Please try the updated code. – falsetru May 12 '17 at 09:32
  • environment variables are not update in the system .no changes – user092 May 12 '17 at 09:39
  • @user092, Are you trying to change shell's env variable? Updating env vars of the process itself is possible. Changed env variables can be inherited to child processes. But, it's not possible to update parent process' env vars. – falsetru May 12 '17 at 09:42
  • @user092, just run `source /home/user/env_script.env` in shell. – falsetru May 12 '17 at 09:47
  • yes i tried this subprocess.call(["source "/home/user/env_script.env"],shell=True).But this did't work for me .I want to call source from python script – user092 May 12 '17 at 09:50
  • @user092, no 'source ..' in shell! Without subprocess. subprocess creates a child process. Changes in child (sub) process does not affect python process and its parent process (shell = parent process of python process). – falsetru May 12 '17 at 09:53
  • ok .How can i call the /home/user/env_script.env in my python script ..Could you please provide any reference – user092 May 12 '17 at 09:56
  • @user092, Please check the last method in the answer. There no way to chnage parent shell's env variable in python as far as I know. – falsetru May 12 '17 at 09:58
  • I can't create any wrapper script or separate shell script .only one python standalone script .that is my requirement .so what ever i call should be from python script. – user092 May 12 '17 at 10:00
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/144049/discussion-between-user092-and-falsetru). – user092 May 12 '17 at 10:00
0

Modern operating systems do not allow a child process to change the environment of its parent. The environment can only be changed for the current process and its descendants. And a Python interpreter is a child of the calling shell.

That's the reason why source is not an external command but is interpreted directly by the shell to allow a change in its environment.

It used to be possible in the good old MS/DOS system with the .COM executable format. A .com executable file had a preamble of 256 (0x100) bytes among which was a pointer to the COMMAND.COM's environment string! So with low level memory functions, and after ensuring not overwriting anything past the environment, a command could change directly its parent environment.

It may still be possible in modern OS, but require cooperation from system. For example Windows can allow a process to get read/write access to the memory of another process, provided the appropriate permissions are set. But this is really a hacky way, and I would not dare doing this in Python.

TL/DR: if your requirement is to change the environment of the calling shell from a Python script, you have misunderstood your requirement.


But what is easy is to start a new shell with a modified environment:

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()
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • Interesting but this answer is completely off topic, it doesn't answer the question in the original post – Sunchock Mar 06 '22 at 21:16