9

I'm trying to modify the environment variables on a parent shell from within Python. What I've attempted so far hasn't worked:

~ $ export TESTING=test
~ $ echo $TESTING
test
~ $
~ $
~ $ python
Python 2.7.10 (default, Jun  1 2015, 18:05:38)
[GCC 4.9.2] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.environ['TESTING']
'test'
>>> os.environ['TESTING'] = 'changed'
>>> os.environ['TESTING']
'changed'
>>> quit()
~ $
~ $
~ $ echo $TESTING
test

That's all I've been able to come up with. Can it be done? How do I set environment variables of parent shell in Python?

jww
  • 97,681
  • 90
  • 411
  • 885
ewok
  • 20,148
  • 51
  • 149
  • 254
  • 3
    Modifying the environment of a parent process amounts to modifying its memory space, meaning that in general, no, it's not possible. – chepner Mar 03 '16 at 19:05

2 Answers2

12

This isn't possible.

Child processes inherit their environments from their parents rather than share them. Therefore any modifications you make to your environment will be reflected only in the child (python) process. Practically, you're just overwriting the dictionary the os module has created based on your environment of your shell, not the actual environment variables of your shell.

https://askubuntu.com/questions/389683/how-we-can-change-linux-environment-variable-in-python

Why can't environmental variables set in python persist?

Community
  • 1
  • 1
DaveBensonPhillips
  • 3,134
  • 1
  • 20
  • 32
8

What you can do is to parse the output of a Python command as shell commands, by using the shell's Command Substitution functionality, which is more often used to evaluate a command in-line of another command. E.g. chown `id -u` /somedir.

In your case, you need to print shell commands to stdout, which will be evaluated by the shell. Create your Python script and add:

testing = 'changed'
print 'export TESTING={testing}'.format(testing=testing)

then from your shell:

$ `python my_python.sh`
$ echo TESTING
changed

Basically, any string will be interpreted by the shell, even ls, rm etc

Alastair McCormack
  • 26,573
  • 8
  • 77
  • 100
  • 1
    Using backticks to run the expansion result [is buggy for all the reasons given in BashFAQ #50](https://mywiki.wooledge.org/BashFAQ/050); if you want to treat a string as code for a shell, use `eval` after taking steps (like use of the `shlex.quote()`/`pipes.quote()` functions) to ensure it's safe to process in that way. (The better practice is to pass an *array* out of your shell script and evaluate it as a simple command, but that's a mouthful and notes on doing it right don't fit into a comment, at least, not with a full explanation of why the associated complexity is called for). – Charles Duffy Dec 07 '19 at 03:59