0

I have a context manager that keeps track of time:

import time

class Timer:
    '''A rudimentary context manager for keeping track of running time'''
    def __enter__(self):
        self.timer = time.time()
        self.state = 1
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self.timer = time.time() - self.timer
        self.state = 0

    def __float__(self):
        if self.state:
            return time.time() - self.timer
        else:
            return self.timer

    def __int__(self):
        return int(float(self))

    def __str__(self):
        return str(float(self))

    def __format__(self, format_spec):
        return format(float(self), format_spec)

Clearly, the following is a legitimate use case

def test():
    with Timer() as t:
        time.sleep(1)
        print(f'Time elapsed {t:.2f}s')

My question is, in my case is it safe to use the context manager object after the with statement has exited? Say,

def test():
    with Timer() as t:
        time.sleep(1)

    print(f'Time elapsed {t:.2f}s')
    return t
Andrei
  • 2,585
  • 1
  • 14
  • 17
  • Yes, it is safe. It is no different than an ordinary assignment within that scope. Please read the linked question. – metatoaster Mar 13 '20 at 12:28
  • @metatoaster Yes, that was exactly my question. Could not find it somehow. Thanks. – Andrei Mar 13 '20 at 12:29
  • 1
    It depends on the context manager. When you run `with foo() as f:`, `f` is assigned the return value of `foo().__enter__()`, which is not necessarily `foo()` itself. Further, you can't use features of `f` that depend on `foo().__exit__` not yet having been called. (For example, after `with open(...) as f`; `f` is still a file-like object, but `f.close()` as already been called; you can't read from or write to it again. – chepner Mar 13 '20 at 12:36

0 Answers0