Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #28157 > unrolled thread
| Started by | Ben Finney <ben+python@benfinney.id.au> |
|---|---|
| First post | 2012-08-31 12:36 +1000 |
| Last post | 2012-08-31 12:06 +0100 |
| Articles | 4 — 3 participants |
Back to article view | Back to comp.lang.python
Context manager to save/restore a name binding Ben Finney <ben+python@benfinney.id.au> - 2012-08-31 12:36 +1000
Re: Context manager to save/restore a name binding Peter Otten <__peter__@web.de> - 2012-08-31 08:27 +0200
Re: Context manager to save/restore a name binding Ben Finney <ben+python@benfinney.id.au> - 2012-08-31 19:32 +1000
Re: Context manager to save/restore a name binding Chris Withers <chris@python.org> - 2012-08-31 12:06 +0100
| From | Ben Finney <ben+python@benfinney.id.au> |
|---|---|
| Date | 2012-08-31 12:36 +1000 |
| Subject | Context manager to save/restore a name binding |
| Message-ID | <87oblrbxea.fsf@benfinney.id.au> |
Howdy all,
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?
--
\ “When a well-packaged web of lies has been sold to the masses |
`\ over generations, the truth will seem utterly preposterous and |
_o__) its speaker a raving lunatic.” —Dresden James |
Ben Finney
[toc] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2012-08-31 08:27 +0200 |
| Message-ID | <mailman.4000.1346395794.4697.python-list@python.org> |
| In reply to | #28157 |
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)
[toc] | [prev] | [next] | [standalone]
| From | Ben Finney <ben+python@benfinney.id.au> |
|---|---|
| Date | 2012-08-31 19:32 +1000 |
| Message-ID | <87k3wfbe51.fsf@benfinney.id.au> |
| In reply to | #28160 |
Peter Otten <__peter__@web.de> writes: > You should wrap yield in a try ... finally. You might allow setting > the new value in the manager (untested): Thank you, both good advice. I would still like to know if Python already has something to make this unnecessary. -- \ “Compulsory unification of opinion achieves only the unanimity | `\ of the graveyard.” —Justice Roberts in 319 U.S. 624 (1943) | _o__) | Ben Finney
[toc] | [prev] | [next] | [standalone]
| From | Chris Withers <chris@python.org> |
|---|---|
| Date | 2012-08-31 12:06 +0100 |
| Message-ID | <mailman.4006.1346411157.4697.python-list@python.org> |
| In reply to | #28157 |
Hi Ben,
On 31/08/2012 03:36, Ben Finney wrote:
> 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?
Depends on the context (ho ho..), but if it's testing, then have a look at:
http://packages.python.org/testfixtures/mocking.html#the-context-manager
There's plenty of other goodies you may like in there too...
cheers,
Chris
--
Simplistix - Content Management, Batch Processing & Python Consulting
- http://www.simplistix.co.uk
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web