getekha getekha - 1 month ago 6x
Python Question

Emulating Bash 'source' in Python

I have a script that looks something like this:

export foo=/tmp/foo
export bar=/tmp/bar

Every time I build I run 'source init_env' (where init_env is the above script) to set up some variables.

To accomplish the same in Python I had this code running,

reg = re.compile('export (?P<name>\w+)(\=(?P<value>.+))*')
for line in open(file):
m = reg.match(line)
if m:
name ='name')
value = ''
value ='value')
os.putenv(name, value)

But then someone decided it would be nice to add a line like the following to the

export PATH="/foo/bar:/bar/foo:$PATH"

Obviously my Python script fell apart. I could modify the Python script to handle this line, but then it'll just break later on when someone comes up with a new feature to use in the

The question is if there is an easy way to run a Bash command and let it modify my


The problem with your approach is that you are trying to interpret bash scripts. First you just try to interpret the export statement. Then you notice people are using variable expansion. Later people will put conditionals in their files, or process substitutions. In the end you will have a full blown bash script interpreter with a gazillion bugs. Don't do that.

Let Bash interpret the file for you and then collect the results.

You can do it like this:

#! /usr/bin/env python

import os
import pprint
import subprocess

command = ['bash', '-c', 'source init_env && env']

proc = subprocess.Popen(command, stdout = subprocess.PIPE)

for line in proc.stdout:
  (key, _, value) = line.partition("=")
  os.environ[key] = value



Make sure that you handle errors in case bash fails to source init_env, or bash itself fails to execute, or subprocess fails to execute bash, or any other errors.

Read the documentation on subprocess for more details.

Note: this will only capture variables set with the export statement, as env only prints exported variables.


Note that the Python documentation says that if you want to manipulate the environment you should manipulate os.environ directly instead of using os.putenv(). I consider that a bug, but I digress.