I guess that’s true for most cases when we’re dealing with releasable resources, like files, DB connections, etc. However, I would say that nothing actually restricts one from using context managers for different purposes. Like, for example, I am using the following class to track execution time:
import time
from timeit import default_timer
class Timer:
"""Simple util to measure execution time.
Examples
--------
>>> import time
>>> with Timer() as timer:
... time.sleep(1)
>>> print(timer)
00:00:01
"""
def __init__(self):
self.start = None
self.elapsed = None
def __enter__(self):
self.start = default_timer()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.elapsed = default_timer() - self.start
def __float__(self):
return self.elapsed
def __str__(self):
return self.verbose()
def verbose(self):
if self.elapsed is None:
return '<not-measured>'
return time.strftime('%H:%M:%S', time.gmtime(self.elapsed))
So, essentially, it is a context manager but it doesn’t really release any resources. I guess that similar examples could probably be found in the contextlib
module. Like, stdout redirection or warnings/exceptions suppression.
In general, from my point of view, the context manager could be thought of as being an execution scope with some specific condition enforced.