Ben Finney wrote: > I have written a context manager to save and restore a name binding:: > > import contextlib > > @contextlib.contextmanager > def preserve_value(namespace, name): > """ A context manager to preserve, then restore, the specified > binding. > > :param namespace: The namespace object (e.g. a class or dict) > containing the name binding. > :param name: The name of the binding to be preserved. > :yield: None. > > When the context manager is entered, the current value bound > to `name` in `namespace` is saved. When the context manager is > exited, the binding is re-established to the saved value. > > """ > saved_value = getattr(namespace, name) > yield > setattr(namespace, name, saved_value) > > The use case is <URL: http://stackoverflow.com/a/6811921/70157>, where > it's used like this:: > > with preserve_value(sys, 'dont_write_bytecode'): > sys.dont_write_bytecode = True > module = imp.load_module(…) > > That way, I can set ‘sys.dont_write_bytecode’ to the value I need in > this part of the code, knowing that however the code continues the > previous value of that setting will be restored to whatever it was > before I touched it. > > Have I re-invented a context manager which already exists? Is there a > better way to do what ‘preserve_value’ is doing? You should wrap yield in a try ... finally. You might allow setting the new value in the manager (untested):
import contextlib missing = object() @contextlib.contextmanager def preserve_attr(namespace, name, value=missing): saved_value = getattr(namespace, name) if value is not missing: setattr(namespace, name, value) try: yield finally: setattr(namespace, name, saved_value) -- http://mail.python.org/mailman/listinfo/python-list