6

Is it possible using Python 3.5 to create and update environment variables in Windows and Linux so that they get persisted?

At the moment I use this:

import os
os.environ["MY_VARIABLE"] = "TRUE"

However it seems as if this does not "store" the environment variable persistently.

Robert Strauch
  • 12,055
  • 24
  • 120
  • 192
  • 2
    Environment variables are specific to each process; you aren't storing them to some sort of persistent external "environment". If you want to store data, consider using a file. – user2357112 Jan 15 '16 at 22:31
  • 1
    Just found this question: http://stackoverflow.com/questions/716011/why-cant-environmental-variables-set-in-python-persist – Robert Strauch Jan 15 '16 at 22:31
  • 1
    Also this one: http://stackoverflow.com/questions/17657686/is-it-possible-to-set-an-environment-variable-from-python-permanently – OneCricketeer Jan 15 '16 at 22:32
  • One way you could hack it: You could `exec` a bash shell, which would overwrite your Python process with a bash process that would inherit the new environment variables. However, this would not inherit any bash specific stuff like aliases, since those can't be inherited from parent to child (the Python process never would have gotten them in the first place). – eestrada Jan 15 '16 at 22:41
  • On Windows you can try to use [py_setenv][1] module that will update user/system variable via registry [1]: https://github.com/beliaev-maksim/py_setenv – Beliaev Maksim Mar 10 '21 at 11:59

2 Answers2

7

I'm speaking for Linux here, not sure about Windows.

Environment variables don't work that way. They are a part of the process (which is what you modify by changing os.environ), and they will propagate to child processes of your process (and their children obviously). They are in-memory only, and there is no way to "set and persist" them directly.

There are however several configuration files which allow you to set the environment on a more granular basis. These are read by various processes, and can be system-wide, specific to a user, specific to a shell, to a particular type of process etc.

Some of them are:

  • /etc/environment for system-wide variables
  • /etc/profile for shells (and their children)
  • Several other shell-specific files in /etc
  • Various dot-files in a user's home directory such as .profile, .bashrc, .bash_profile, .tcshrc and so on. Read your shell's documentation.
  • I believe that there are also various ways to configure environment variables launched from GUIs (e.g. from the gnome panel or something like that).

Most of the time you'll want to set environment variables for the current user only. If you only care about shells, append them to ~/.profile in this format:

NAME="VALUE"

AaronI
  • 842
  • 6
  • 12
5

The standard way to 'persist' an environment variable is with a configuration file. Write your application to open the configuration file and set every NAME=VARIABLE pair that it finds. Optionally this step could be done in a wrapper startup script.

If you wish to 'save' the state of a variable, you need to open the configuration file and modify its contents. Then when it's read in again, your application will set the environment accordingly.

You could of course store the configuration in some other way. For example in a configuration_settings class that you pickle/shelve. Then on program startup you read in the pickled class and set the environment. The important thing to understand is that when a process exits its environment is not saved. Environments are inherited from the parent process as an intentional byproduct of forking.

Config file could look like:

NAME=VALUE
NAME2=VALUE2
...

Or your config class could look like:

class Configuration():
    env_vars = {}
    import os
    def set(name, val):
        env_vars[name] = val
        os.environ[name] = val
    def unset(name):
        del env_vars[name]
        del os.environ[name]
    def init():
        for name in env_vars:
            os.environ[name] = env_vars[name]

Somewhere else in our application

import shelve
filename = "config.db"
d = shelve.open(filename)

# get our configuration out of shelve
config = d['configuration']

# initialize environment
config.init()

# setting an environment variable
config.set("MY_VARIABLE", "TRUE")

#unsetting
config.unset("MY_VARIABLE")

# save our configuration
d['configuration'] = config

Code is not tested but I think you get the jist.

ktbiz
  • 586
  • 4
  • 13