29

From what I've read, any changes to the environment variables in a Python instance are only available within that instance, and disappear once the instance is closed. Is there any way to make them stick by committing them to the system?

The reason I need to do this is because at the studio where I work, tools like Maya rely heavily on environment variables to configure paths across multiple platforms.

My test code is

import os
os.environ['FAKE'] = 'C:\\'

Opening another instance of Python and requesting os.environ['FAKE'] yields a KeyError.

NOTE: Portability will be an issue, but the small API I'm writing will be able to check OS version and trigger different commands if necessary.

That said, I've gone the route of using the Windows registry technique and will simply write alternative methods that will call shell scripts on other platforms as they become requirements.

Soviut
  • 88,194
  • 49
  • 192
  • 260
  • 1
    For windows I can recommend a module to set variables through registry. Also has CLI app: https://github.com/beliaev-maksim/py_setenv this has good control on user/system level and does not have limit in length as setx – Beliaev Maksim Feb 12 '21 at 19:35

12 Answers12

22

You can using SETX at the command-line.

By default these actions go on the USER env vars. To set and modify SYSTEM vars use the /M flag

import os
env_var = "BUILD_NUMBER"
env_val = "3.1.3.3.7"
os.system("SETX {0} {1} /M".format(env_var,env_val))
Jordan Stefanelli
  • 1,446
  • 1
  • 13
  • 13
  • 10
    The big problem with `SETX` on windows is that it doesn't change the current environment or even command shells launched from it - you will have to exit the shell and start a new one. – Steve Barnes Oct 24 '16 at 09:31
  • 1
    What am I missing - this seems the easiest? – Steven Nov 10 '16 at 00:27
  • 3
    BEWARE: this can truncate your PATH env variable e.g. to first 1024 symbols depending on the system. Better make a backup and work out a restoration strategy first. – Bob Jul 02 '19 at 19:12
  • @SteveBarnes Is there a way to set an environment without restarting the shell or IDE? – datalifenyc Aug 24 '21 at 12:16
  • 1
    @datalifenyc - Not that I have found. – Steve Barnes Aug 25 '21 at 08:15
10

make them stick by committing them to the system?

I think you are a bit confused here. There is no 'system' environment. Each process has their own environment as part its memory. A process can only change its own environment. A process can set the initial environment for processes it creates.

If you really do think you need to set environment variables for the system you will need to look at changing them in the location they get initially loaded from like the registry on windows or your shell configuration file on Linux.

Zoredache
  • 37,543
  • 7
  • 45
  • 61
  • 11
    By 'system' environment variables, Soviut is referring to variables that are established system-wide, e.g. often /etc/profile in Unix or as a System (vs. User) environment variable in Windows. I think this is clear from his context. – Jeff Bauer Jan 28 '09 at 18:32
6

Seems like there is simplier solution for Windows

import subprocess 
subprocess.call(['setx', 'Hello', 'World!'], shell=True)
  • You must use this carefully, as this overrides the current variable's value if the variable already exists. – RaduS Jul 02 '20 at 07:21
  • Be careful with this as it will truncate your value to the first 1024 characters! – Hossein Apr 27 '21 at 07:42
6

Under Windows it's possible for you to make changes to environment variables persistent via the registry with this recipe, though it seems like overkill.

To echo Brian's question, what are you trying to accomplish? There is probably an easier way.

Jeff Bauer
  • 13,890
  • 9
  • 51
  • 73
  • 3
    How come setting environment's variable persistently from (to be) the standard language of system administrators could be called overkill?? – Piotr Dobrogost Sep 08 '11 at 20:11
  • 2
    @Jeff, really? You can't see why does one want to make an environment variable permanent? It's an ancient issue! :) (Hint: Passing variables between programs) And then, what does it mean "there is probably an easier way"? Easier way for what? :) – Apostolos Jan 15 '20 at 18:06
5

I don't believe you can do this; there are two work-arounds I can think of.

  1. The os.putenv function sets the environment for processes you start with, i.e. os.system, popen, etc. Depending on what you're trying to do, perhaps you could have one master Python instance that sets the variable, and then spawns new instances.

  2. You could run a shell script or batch file to set it for you, but that becomes much less portable. See this article:

http://code.activestate.com/recipes/159462/

DNS
  • 37,249
  • 18
  • 95
  • 132
3

Think about it this way.

You're not setting shell environment variables.

You're spawning a subshell with some given environment variable settings; this subshell runs your application with the modified environment.

S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • Think about it this way. He **is** setting system-wide, default shell environment variables :) That being said your perspective is valid and points towards solving the problem by *replacing* executables with Python scripts setting environment and then running these executables. +1 – Piotr Dobrogost Sep 08 '11 at 21:03
  • 1
    @Piotr Dobrogost: Think about it this way. Setting system-wide default shell environment variables doesn't seem like a very good idea in general. Been there, done that, didn't like the administrative nightmare it caused when people needed unique environments. – S.Lott Sep 08 '11 at 21:07
2

According to this discussion, you cannot do it. What are you trying to accomplish?

Brian
  • 25,523
  • 18
  • 82
  • 173
  • I'm literally trying to make an environment switcher that adjusts environment variables across several platforms. – Soviut Jan 28 '09 at 17:04
  • @Soviut, Why are you trying to change environment variables? – Zoredache Jan 28 '09 at 17:28
  • 2
    Its so we can switch between different projects that our 3D applications use. They rely heavily on environment variables. – Soviut Jan 28 '09 at 21:22
2

You are forking a new process and cannot change the environment of the parent process as you cannot do if you start a new shell process from the shell

leancz
  • 688
  • 5
  • 21
1

You might want to try Python Win32 Extensions, developed by Mark Hammond, which is included in the ActivePython (or can be installed separately). You can learn how to perform many Windows related tasks in Hammond's and Robinson's book.

Using PyWin32 to access windows COM objects, a Python program can use the Environment Property (a collection of environment variables) of the WScript.Shell object.

Sridhar Ratnakumar
  • 81,433
  • 63
  • 146
  • 187
gimel
  • 83,368
  • 10
  • 76
  • 104
  • 1
    What's the advantage of using the above to invoking *setx* standard Windows program? It's not any more portable and it's more complicated. – Piotr Dobrogost Sep 08 '11 at 20:27
0

Try to use py-setenv that will allow you to set variable via registry

python -m pip install py-setenv

Beliaev Maksim
  • 968
  • 12
  • 21
-1

In case someone might need this info. I realize this was asked 7 yrs ago, but even I forget how sometimes. .

Yes there is a way to make them "stick" in windows. Simply go control panel, system, advanced system settings,when the system properties window opens you should see an option (button) for Environment Variables. .The process for getting to this is a little different depending on what OS you're using (google it).

Choose that (click button), then the Environment Variables window will open. It has 2 split windows, the top one should be your "User Variables For yourusername". . .choose "new", then simply set the variable. For instance one of mine is "Database_Password = mypassword".

Then in your app you can access them like this: import os, os.environ.get('Database_Password'). You can do something like pass = os.environ.get('Database_Password').

Chris Kavanagh
  • 451
  • 1
  • 5
  • 15
  • Not sure why this was down voted. This is an answer to the question, unless the question was "how to do this programmatically with Python." For some reason I thought he was asking about Windows specifically, and now I realize that wasn't the exact question. – Chris Kavanagh Aug 16 '17 at 05:17
  • 1
    Yes, programmatically is what the OP is asking. – Wolfgang Kuehn Sep 10 '21 at 18:06
-1

From within Python? No, it can't be done!

If you are not bound to Python, you should consider using shell scripts (sh, bash, etc). The "source" command allows you to run a script that modifies the environment and will "stick" like you want to the shell you "sourced" the script in. What's going on here is that the shell executes the script directly rather creating a sub-process to execute the script.

This will be quite portable - you can use cygwin on windows to do this.

Daniel Paull
  • 6,797
  • 3
  • 32
  • 41
  • 1
    The idea was to keep things as contained as possible within Python, not install a huge library like cygwin just to get a few bash commands out of it. – Soviut Jan 30 '09 at 03:04
  • As of other answers this can indeed be done. So this answer is wrong. – Wolfgang Kuehn Sep 10 '21 at 18:08
  • Lol. 12 years later and being told I'm wrong. I'm going to double down on my answer because what was asked was about "changes to the environment variables in a Python instance are only available within that instance" and how to make them "stick". You can change the environment of your process all you like and it won't stick by definition. If you change the system default environment (as per other answers) then it doesn't change the environment variables in the python instance, which appears to be a requirement, so other answers are wrong given how the question was asked. – Daniel Paull Sep 16 '21 at 05:51