Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - temporarily modify the current process's environment

I use the following code to temporarily modify environment variables.

@contextmanager def _setenv(**mapping):     """``with`` context to temporarily modify the environment variables"""     backup_values = {}     backup_remove = set()     for key, value in mapping.items():         if key in os.environ:             backup_values[key] = os.environ[key]         else:             backup_remove.add(key)         os.environ[key] = value      try:         yield     finally:         # restore old environment         for k, v in backup_values.items():             os.environ[k] = v         for k in backup_remove:             del os.environ[k] 

This with context is mainly used in test cases. For example,

def test_myapp_respects_this_envvar():     with _setenv(MYAPP_PLUGINS_DIR='testsandbox/plugins'):         myapp.plugins.register()         [...] 

My question: is there a simple/elegant way to write _setenv? I thought about actually doing backup = os.environ.copy() and then os.environ = backup .. but I am not sure if that would affect the program behavior (eg: if os.environ is referenced elsewhere in the Python interpreter).

like image 682
Sridhar Ratnakumar Avatar asked Jan 13 '10 19:01

Sridhar Ratnakumar


People also ask

How do you set an environment variable in Python?

Environ and set default:With the environ dictionary variable value of the environment variable can be set by passing the key in the dictionary and assigning the value to it. With setdefault a default value can be assigned to the environment variable. Bypassing the key and the default value in the setdefault method.

What are the four 4 environment variables of a Python?

Environment variables is the set of key-value pairs for the current user environment. They are generally set by the operating system and the current user-specific configurations.

How do I permanently set an environment variable in Python?

To set and get environment variables in Python you can just use the os module: import os # Set environment variables os. environ['API_USER'] = 'username' os. environ['API_PASSWORD'] = 'secret' # Get environment variables USER = os.

Can environment variables change during execution?

No. This is not possible. One process can never directly manipulate the environment of a different already-running process.


2 Answers

I suggest you the following implementation:

import contextlib import os   @contextlib.contextmanager def set_env(**environ):     """     Temporarily set the process environment variables.      >>> with set_env(PLUGINS_DIR=u'test/plugins'):     ...   "PLUGINS_DIR" in os.environ     True      >>> "PLUGINS_DIR" in os.environ     False      :type environ: dict[str, unicode]     :param environ: Environment variables to set     """     old_environ = dict(os.environ)     os.environ.update(environ)     try:         yield     finally:         os.environ.clear()         os.environ.update(old_environ) 

EDIT: more advanced implementation

The context manager below can be used to add/remove/update your environment variables:

import contextlib import os   @contextlib.contextmanager def modified_environ(*remove, **update):     """     Temporarily updates the ``os.environ`` dictionary in-place.      The ``os.environ`` dictionary is updated in-place so that the modification     is sure to work in all situations.      :param remove: Environment variables to remove.     :param update: Dictionary of environment variables and values to add/update.     """     env = os.environ     update = update or {}     remove = remove or []      # List of environment variables being updated or removed.     stomped = (set(update.keys()) | set(remove)) & set(env.keys())     # Environment variables and values to restore on exit.     update_after = {k: env[k] for k in stomped}     # Environment variables and values to remove on exit.     remove_after = frozenset(k for k in update if k not in env)      try:         env.update(update)         [env.pop(k, None) for k in remove]         yield     finally:         env.update(update_after)         [env.pop(k) for k in remove_after] 

Usage examples:

>>> with modified_environ('HOME', LD_LIBRARY_PATH='/my/path/to/lib'): ...     home = os.environ.get('HOME') ...     path = os.environ.get("LD_LIBRARY_PATH") >>> home is None True >>> path '/my/path/to/lib'  >>> home = os.environ.get('HOME') >>> path = os.environ.get("LD_LIBRARY_PATH") >>> home is None False >>> path is None True 

EDIT2

A demonstration of this context manager is available on GitHub.

like image 111
Laurent LAPORTE Avatar answered Sep 17 '22 15:09

Laurent LAPORTE


_environ = dict(os.environ)  # or os.environ.copy() try:      ...  finally:     os.environ.clear()     os.environ.update(_environ) 
like image 45
Ignacio Vazquez-Abrams Avatar answered Sep 21 '22 15:09

Ignacio Vazquez-Abrams