I'm using the next code to execute a bash script that defines a lot of environment variables:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import subprocess
# Code used to get the value of variable before the call to my script
command = "echo $MYDIR"
ps = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
my_dir = ps.communicate()[0]
print "my_dir", my_dir
subprocess.Popen(["/bin/sh", "/home/user/env_file"])
# Code used to get the value of established variable
command = "echo $MYDIR"
ps = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
my_dir = ps.communicate()[0]
print "my_dir", my_dir
The content of my /home/user/env_file is the next:
#!/bin/bash
export MYDIR=/home/user
export MYDIR2=/home/user2
export MYDIR3=/home/user3
export MYDIR4=/home/user4
export MYDIR5=/home/user5
export MYDIR6=/home/user6
export MYDIR7=/home/user7
export MYDIR8=/home/user8
export MYDIR9=/home/user9
export MYDIR10=/home/user10
export MYDIR11=/home/user11
export MYDIR12=/home/user12
export MYDIR13=/home/user13
export MYDIR14=/home/user14
export MYDIR15=/home/user15
export MYDIR16=/home/user16
When I execute the Python code I do not get any value for my_dir variable. How can I perform this?
Best regards.
解决方案
The only way for a process to influence its parent's environment (absent ugly hacks abusing development/debugging facilities) is with that parent process's direct involvement (which is why one runs eval "$(ssh-agent)" -- evaling its output is, in this case, the cooperation needed from the parent to let ssh-agent set environment variables in the process that started it). Consider the following shell wrapper:
#!/usr/bin/env bash
# Save this script as "envvar-extraction-wrapper"
exec {orig_stdout}>&1 # create a backup of stdout
exec >&2 # and then use stderr while sourcing the child script
source "$@" # run arbitrary script with arbitrary arguments *in this shell*
# note that this means that if it runs "exit", we abort prematurely
while read -r varname; do
printf '%s\0%s\0' "$varname" "${!varname}" >&$orig_stdout
done <
...called from the following Python:
import subprocess, itertools, os
ps = subprocess.Popen(['envvar-extraction-wrapper', '/home/user/env_file'],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
(stdout, stderr) = ps.communicate()
items_iter = iter(stdout.split('\0'))
for (k,v) in itertools.izip(items_iter, items_iter):
os.environ[k]=v