1

Is it possible to create a shell object and manipulate it without losing it's data after command execution?

from subprocess import *
sh.Popen('/bin/bash', stdout=PIPE)
sh.communicate('source /path/to/file/env.sh')
print os.getenv('ENV_VAR1')

ENV_VAR1 should be available after sourcing /path/to/file/env.sh but it's not. This part of code is not working as expected, how can I make it work?

Here is another try which is not working as well

os.system('source env.sh; echo $ENV_VAR1') #Prints out correct value
os.system('echo $ENV_VAR1') #Prints nothing
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
PYPL
  • 1,819
  • 1
  • 22
  • 45

2 Answers2

4

You could echo $ENV_VAR1, and use communicate to return the result from stdout:

import subprocess
proc = subprocess.Popen('source /path/to/file/env.sh; echo $ENV_VAR1', 
                        stdout=PIPE, shell=True)
env_var1, err = proc.communicate()
print(env_var1)

Another option might be to use Miki Tebeka's source function:

import subprocess
import os

def source(script, update=True):
    """
    source a file and return the environment as a dict.
    http://pythonwise.blogspot.fr/2010/04/sourcing-shell-script.html (Miki Tebeka)
    """
    proc = subprocess.Popen("source %s; env -0" % script, stdout=subprocess.PIPE, 
                            shell=True)
    output, err = proc.communicate()
    env = dict((line.split("=", 1) for line in output.split('\x00') if line))
    if update:
        os.environ.update(env)
    return env

source('/path/to/env.sh')
print(os.environ['ENV_VAR1'])

If /path/to/file/env.sh contains

ENV_VAR1=FOO
export ENV_VAR1

the script above prints

FOO

Above, I made a small change to the function so that env uses a null byte (\x00) to separate output lines. This makes it possible to parse name/value pairs that span multiple lines.

Community
  • 1
  • 1
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • good solution for bash, but not working is the sourcefile is `tcsh` file, `proc.communicate()` returns empty tuple – PYPL Jul 20 '15 at 12:31
  • Using dot, as in `. /path/to/env.sh`, to source a file is a bash-ism. I think both bash and tcsh can use `source /path/to/env.sh` however. I've changed the code (in the `source` function) above to fix this. – unutbu Jul 20 '15 at 12:46
0

This isn't a Python issue. Environment variables are only visible to the process in which they are set and any child processes. In these examples you are trying to set environment variables in a child and access them from the parent, which simply doesn't work.

If you want to communicate these values back to the parent you will need to arrange for some sort of explicit communication (e.g, having the child write the values to stdout and read them from the parent).

larsks
  • 277,717
  • 41
  • 399
  • 399