import time
49 Context Manager (Custom)
49.1 @contextmanager
Decorator
49.1.1 file_manager()
import time
from contextlib import contextmanager
from typing import Generator, IO, Any
@contextmanager
def file_manager(path: str, mode: str) -> Generator[IO, Any, None]:
file: IO = open(path, mode)
print('Opening file...')
try:
yield file
finally:
print('Closing file...')
if file:
file.close()
with file_manager("hello.txt", mode="r") as f:
raise Exception("something bad happens!")
print(f.read())
Opening file...
Closing file...
--------------------------------------------------------------------------- Exception Traceback (most recent call last) Cell In[6], line 2 1 with file_manager("hello.txt", mode="r") as f: ----> 2 raise Exception("something bad happens!") 3 print(f.read()) Exception: something bad happens!
49.1.2 timer()
⭐️
import time
from contextlib import contextmanager
from typing import Generator, IO, Any
@contextmanager
def timer():
"""Context manager for measuring execution time.
Returns
-------
callable
A lambda function that returns the elapsed time
Example
-------
```python
with timer() as t:
# some code to measure
pass
t = t()
t # prints elapsed time
```
"""
float = time.perf_counter()
start_time: try:
yield lambda: elapsed
finally:
= time.perf_counter() - start_time
elapsed print(f'Time: {elapsed:.4f}s')
with timer() as t:
= ""
text for i in range(100_000):
+= str(i) text
Time: 0.3740s
t()
0.3740487500326708
49.1.3 timer()
start & end
from datetime import datetime
@contextmanager
def timer2():
float = time.perf_counter()
start_time: print(f"Started at: {datetime.now():%H:%M:%S}")
try:
yield lambda: elapsed
finally:
= time.perf_counter() - start_time
elapsed print(f"Ended at: {datetime.now():%H:%M:%S}")
print(f'Time: {elapsed:.4f}s')
with timer2() as t2:
= ""
text for i in range(100_000):
+= str(i) text
Started at: 16:36:24
Ended at: 16:36:24
Time: 0.3461s
49.2 Timer Class
class Timer:
def __init__(self, name: str):
self.name = name
def __enter__(self):
self._start_time = time.perf_counter()
print(f"Starting timer for {self.name}")
return self
def __exit__(self, exc_type, exc_value, traceback):
self._end_time = time.perf_counter()
= self._end_time - self._start_time
elapsed_time print(f"Timer for {self.name} finished. Elapsed time: {elapsed_time:.4f} seconds")
with Timer("for...loop timer") as timer:
print(timer.name)
for _ in range(1000000):
pass
Starting timer for for...loop timer
for...loop timer
Timer for for...loop timer finished. Elapsed time: 0.0449 seconds