0

I defined a shell script with a python script inside on the fly. Getting variables from shell to Python works fine, but the other way round does not work as expected. My Idea was to create an env variable os.environ["NEW_VAR"] = "test", but when trying is echo it, it is just None.

#!/bin/bash

args=("$@")

GIT_PASSWORD=${args[0]}
export GIT_PASSWORD=$GIT_PASSWORD

python - << EOF

import os

print(os.environ.get("GIT_PASSWORD"))
os.environ["NEW_VAR"] = "test"
                                                          
EOF

echo $GIT_PASSWORD
echo $NEW_VAR

echo "Back to bash"
  1. Why does that not work and 2. What is the correct way to pass a variable here? Thank you!
Data Mastery
  • 1,555
  • 4
  • 18
  • 60
  • 6
    A child process cannot affect the environment of its parent. This is not specific to Python. – chepner Aug 01 '22 at 16:48
  • When changing the environment variables of a currently running process (in this case, you start a python process and they change inside there) then, if I'm not mistaken, the changes will only be visible to that process and any child processes created after the variables were set. A better way to communicate might be to have the python write to stdout and have bash read that or work in one context (i.e. python the entire time) – Corey Ogburn Aug 01 '22 at 16:48
  • 1
    As an aside, you don't have to reassign a value to a variable as part of an `export`. `GIT_PASSWORD` already has a value; all you need to do is tell the shell that it is an environment variable with `export GIT_PASSWORD`. *Names* are exported, not values. When you run Python, it will see in its environment whatever value `GIT_PASSWORD` had when Python started, regardless of what the value was when you first exported `GIT_PASSWORD`. – chepner Aug 01 '22 at 16:50
  • Important to note that it's not `None`, it's undefined, so Bash treats it as the empty string. – wjandrea Aug 01 '22 at 16:50
  • 2
    To pass variables in reverse direction just print them and use this output in bash. – STerliakov Aug 01 '22 at 16:56
  • @SUTerliakov: Can you show how this is done? – Data Mastery Aug 01 '22 at 17:03
  • What are you trying to accomplish with this exactly? Beware the [XY problem](https://meta.stackexchange.com/q/66377/343832); give context. If the Python script only ever creates one variable, it'd be easiest to just print its value and have Bash [capture the output](/q/4651437/4518341) like `NEW_VAR=$(python -c 'print("test")')`. On the other hand, if it's *dynamic* what variables the Python script creates, you could maybe print code that Bash could `eval`, like `print('NEW_VAR=test')`. – wjandrea Aug 01 '22 at 17:04
  • @wjandrea: I have a Decrypt function, which decrypts a password which is passed via shell. The decrypted value is used git clone a git repository. That´s why I mix these two up (and I can not print the extracted password to stdout) – Data Mastery Aug 01 '22 at 17:08
  • @Data Sorry, why can't you print the password to stdout? – wjandrea Aug 01 '22 at 17:17
  • @wjandrea: This runs in a kubernetes cluster and everything in stdout will be logged to our central logging service – Data Mastery Aug 01 '22 at 17:19
  • 1
    You don't print to stdout doing `SOME_PASSWORD=$(echo "Some input" | python -c 'import sys; do_something(sys.stdin.read())')` – STerliakov Aug 01 '22 at 17:38
  • Ok, I see this seems to work for me! Thank you everybody for your help! – Data Mastery Aug 01 '22 at 17:39

1 Answers1

0

Written in the comments, inheriting environment variables only works from parent to child processes, not the other way round.

if you need shell variables set from a python script you can create the output in your shell script and eval the results:

eval "$(python -c 'print("HELLO=WORLD")')"
echo "$HELLO"

yields WORLD

makefu
  • 116
  • 5
  • 1
    Note that doing this safely with values that aren't hardcoded requires considerably more care to avoid shell injection vulnerabilities. `shlex.quote()` is your friend. – Charles Duffy Aug 05 '22 at 21:41
  • 1
    Shell quoting, too -- `eval "$(...)"` and `echo "$HELLO"` will stop you from having problems when the output of your Python program can be word-split and glob-expanded. – Charles Duffy Aug 05 '22 at 22:12