Welcome, guest | Sign In | My Account | Store | Cart

Writes environment variables using a batch file wrapper. Overcomes an operating system limitation.

Python, 26 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
setvar.bat
----------
@echo off
python setvarp.py %1 %2 %3 %4 %5 %6 %7 %8 %9
settmp
del settmp.bat

setvarp.py
----------
import sys, time, math
key = sys.argv[1]
value = eval(' '.join(sys.argv[2:]))
command = 'set %s=%s\n' % (key, value)
open('settmp.bat', 'w').write(command)


sample command line session
---------------------------
C>setvar ts time.ctime()
C>setvar pi 22.0 / 7.0
C>setvar pyver sys.version
C>set

TS=Sun Oct 27 18:12:23 2002
PI=3.14285714286
PYVER=2.3a0 (#29, Oct 22 2002, 01:41:41) [MSC 32 bit (Intel)]

Environment variables can be read with os.environ. They can be written (for sub-shells only) using os.putenv(key, value). However, there is no direct way to modify the global environment that the python script is running in. The indirect method shown above writes a set command to a temporary batch file which is in the enclosing environment by another batch file used to launch the python script.

In the example above, arbitrary expressions can be evaluated and the result assigned to an environment variable. For security, the eval() function can be replaced with str().

Usually, writing to an environment variable should be avoided in favor of sharing values through a pipe or a common data file. However, when it can't be avoided, the above technique is an effective, though hackish, work-around.

5 comments

kyle brooks 19 years, 5 months ago  # | flag

eval() use. Hmmmm................why are you using eval()?

Mike Meyer 18 years, 5 months ago  # | flag

The Unix version. Doing this on Unix is different. A couple of things Unix does makes it harder: by default, shell scripts are executed by a subshell, using a special syntax to tell the current shell to process a file itself. And you have to tailor the solution to the shell you are using. On the other hand, Unix shells provide features that make this easier - most notably command substituition and the eval command.

The following solution works for modern sh-derived shells.

The Unix version of setvar.py is:

#!/usr/bin/env python

import sys

args = sys.argv[1:]
while args:
    print 'export %s="%s"' % tuple(args[:2])
    del args[:2]
<pre>
You can use this from a shell with eval and command substiution as:


eval $(python setvar.py var1 value1 var2 value3 var3 value3)


and it will set all the variables to the following values.

You can't just shove this into a shell script though, as it would just set the values for the script. You could put it in a shell script and require the user to do ". script", but that's a bit ugly. Fortunately, the target shells have functions, which give us the same effect. So adding
the following to your .profile (or .zprofile, or .bashrc, or ...) will do the trick:
<pre>
setvar() {
   eval $(python ~/src/python/setvar.py "$@")
}
<pre>
if you adjust the path to setvar.py appropriately.

</pre></pre></pre>

Steen Manniche 17 years, 8 months ago  # | flag

Adding an environment variable on unix. I usually do the following check/hack:

keys = os.environ.keys()
from re import search
for key in keys:
   if not search("MY_PATH", key):
      os.environ["MY_PATH"]="/path/to/program"

...which sets the variable for the running instance, but it's not passed on to eg. programs run by the commands module.

Michael Moore 16 years, 6 months ago  # | flag

Well, I needed to set environment variables WHERE the interpreter lives. <p>It is relatively simple to set things in a subshell using some variant of popen with the stdin set to accept a stream from the calling program, but to set from the shell which is running Python so that subshells can inherit...</p>

<p> Here is the Windows program I used to test this method. I also tested it under Solaris, and two flavors of linux using Python 2.2, 2.3 and 2.4 (only 2.4 is tested on Windows Server 2003, not on XP)

</p>

!/usr/bin/python2.4

import os

x = os.environ['Path']

print x

y = 'C:\Python24\;%s' % x

os.environ['Path'] = y

os.system('cmd /C echo %Path% > output')

fp = file('output','r')

print fp.readlines()

fp.close()

<p> If you use this technique, please note that the changes die when the process exits to the system. It is effective only on the process making the changes and any children who inherit the environment. </p>

Paul Moore 12 years, 11 months ago  # | flag

You need "call settmp". Batch files by default chain, rather than nest, so using a simple "settmp" will mean that control never returns, and so settmp.bat is never deleted.

For Powershell on Windows,

env.py:

print("$env:AAA=12")

To invoke:

PS> Invoke-Expression (.\env.py)
PS> $env:AAA
12
Created by Raymond Hettinger on Sun, 27 Oct 2002 (PSF)
Python recipes (4591)
Raymond Hettinger's recipes (97)
HongxuChen's Fav (39)

Required Modules

  • (none specified)

Other Information and Tasks