Skip to content

Instantly share code, notes, and snippets.

@nickrsan
Created June 7, 2016 15:47
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nickrsan/74461397d9af015db3879c7d2e5f3227 to your computer and use it in GitHub Desktop.
Save nickrsan/74461397d9af015db3879c7d2e5f3227 to your computer and use it in GitHub Desktop.
"""
Allows you to pass in a list of environments to get the values of, then pass it back in to reset.
Usage:
original_envs = store_environments(["workspace","mask"]) # gives back a dict with current environment values for workspace and mask
arcpy.env.workspace = my_workspace
arcpy.env.mask = my_raster
# some more code here to do some work with those environments
# When done:
reset_environments(original_envs) # sets the environments back to the values stored in the dict retrieved by store_environments
"""
def store_environments(environments_list):
"""
Given an iterable of environment variables for arcpy, it stores the current values into a dictionary so they can be reset after an operation
:param environments_list:
:return:
"""
stored_environments = {}
for env in environments_list:
stored_environments[env] = arcpy.env.__getitem__(env)
return stored_environments
def reset_environments(stored_environments):
"""
Given a dict of stored environment variables (from store_environments), it resets the environment values to the value in the dictionary
:param stored_environments:
:return:
"""
for env in stored_environments.keys():
arcpy.env.__setitem__(env, stored_environments[env])
@nickrsan
Copy link
Author

nickrsan commented May 31, 2017

Alternatively, a context manager-based approach:

class Env(object):
	def __init__(self, env, value):
		self.env = env
		self.orig_value = arcpy.env.__getitem__(env)
		self.new_value = value

	def __enter__(self, *args, **kwargs):
		arcpy.env.__setitem__(self.env, self.new_value)

	def __exit__(self, *args, **kwargs):
		arcpy.env.__setitem__(self.env, self.orig_value)

usage would be

with Env("workspace",r"C:\myfolder"), Env("mask", r"C:\my_raster.tif"):
    # do interesting things with these environment settings

# and down here, they're back to normal

Inspired by https://gis.stackexchange.com/questions/158753/managing-environment-variables-in-arcpy/158754 and samuel in the Spatial Community Slack

@nickrsan
Copy link
Author

nickrsan commented Jun 27, 2018

Something like the following should work as a dropin replacement for the new EnvManager in Pro 2.2 (https://pro.arcgis.com/en/pro-app/arcpy/classes/envmanager.htm)

class Env(object):
	"""
		Acts as a drop-in replacement for EnvManagers in Pro
	"""
	def __init__(self, **kwargs):
		self.new_values = kwargs
		self.orig_values = {}
		for env in kwargs:  # back up the original values
			self.orig_values[env] = arcpy.env.__getitem__(env)

	def __enter__(self, *args, **kwargs):
		for env in self.new_values:
			arcpy.env.__setitem__(env, self.new_values[env])

	def __exit__(self, *args, **kwargs):
		self.reset()

	def reset(self):
		for env in self.orig_values:
			arcpy.env.__setitem__(env, self.orig_values[env])

if hasattr(arcpy, "EnvManager"):
	EnvManager = arcpy.EnvManager
else:
	EnvManager = Env

@lpinner
Copy link

lpinner commented Sep 13, 2018

I didn't know about the new EnvManager. About time. I've been using the following construct for a while now:

from contextlib import contextmanager

@contextmanager
def env(**kwargs):
    """ context manager for arcpy.env vars """

    old_env = {}
    try:
        for key, val in kwargs.items():
            old_env[key] = getattr(arcpy.env, key)
            setattr(arcpy.env, key, val)

        yield

    except Exception:
        raise

    finally:
        for key, val in old_env.items():
            setattr(arcpy.env, key, val)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment