Python 3.4 provides this neat tool to temporarily redirect stdout:
# From https://docs.python.org/3.4/library/contextlib.html#contextlib.redirect_stdout
with redirect_stdout(sys.stderr):
help(pow)
The code is not super-complicated, but I wouldn't want to write it over and over again, especially since some thought has gone into it to make it re-entrant:
class redirect_stdout:
def __init__(self, new_target):
self._new_target = new_target
# We use a list of old targets to make this CM re-entrant
self._old_targets = []
def __enter__(self):
self._old_targets.append(sys.stdout)
sys.stdout = self._new_target
return self._new_target
def __exit__(self, exctype, excinst, exctb):
sys.stdout = self._old_targets.pop()
I'm wondering if there's a general way to use the with
statement to temporarily change the value of a variable. Two other use cases from sys
are sys.stderr
and sys.excepthook
.
In a perfect world, something like this would work:
foo = 10
with 20 as foo:
print(foo) # 20
print (foo) # 10
I doubt we can make that work, but maybe something like this is possible:
foo = 10
with temporary_set('foo', 20):
print(foo) # 20
print (foo) # 10
I can sort of getting this working by rooting around in globals()
, but it's nothing anyone would choose to use.
UPDATE: while I think my "foo = 10" examples clarified what I'm trying to do, they do not convey an actual use case. Here are two:
- Redirect stderr, much like redirect_stdout
- Temporarily change sys.excepthook. I do a lot of development interactively, and when I add something to excepthook (by wrapping the original function in one of my own, say, to log exceptions using the logging module), I generally want it to get removed at some point. That way I won't have more and more copies of my function wrapping itself. This question confronts a closely related problem.