Skip to content

Commit 32fef85

Browse files
author
David Buchaca
committed
update: context manager example
1 parent 3e2c848 commit 32fef85

2 files changed

Lines changed: 281 additions & 0 deletions

File tree

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "c053fde3",
6+
"metadata": {},
7+
"source": [
8+
"# How to create a context manager\n",
9+
"\n",
10+
"A context manager is a class that needs to have at least two methods:\n",
11+
"\n",
12+
"- **`__enter__`**: executed when the interpreter enters the context block.\n",
13+
"\n",
14+
"\n",
15+
"- **`__exit__`**: executed allways either after the last line in the context block OR if an error happens.\n",
16+
"\n",
17+
"\n",
18+
"### Example: Context manager to print execution time \n",
19+
"\n",
20+
"Let us create a context manager that tells us the execution time of the code within it.\n",
21+
"\n",
22+
"To make it more useful let us print also a user defined string to faciliate knowing what we are timing, in the event we want to time more than one line in a piece of code. "
23+
]
24+
},
25+
{
26+
"cell_type": "code",
27+
"execution_count": 14,
28+
"id": "35fb1490",
29+
"metadata": {},
30+
"outputs": [],
31+
"source": [
32+
"import time\n",
33+
"from time import sleep\n",
34+
"\n",
35+
"class timer():\n",
36+
"\n",
37+
" def __init__(self, name = ''):\n",
38+
" self.start = time.time()\n",
39+
" self.name = name\n",
40+
"\n",
41+
" def __enter__(self):\n",
42+
" pass\n",
43+
"\n",
44+
" def __exit__(self, *args):\n",
45+
" print(f'time {self.name} {round(time.time() - self.start,6)} sec')"
46+
]
47+
},
48+
{
49+
"cell_type": "code",
50+
"execution_count": 24,
51+
"id": "c04fe165",
52+
"metadata": {},
53+
"outputs": [
54+
{
55+
"name": "stdout",
56+
"output_type": "stream",
57+
"text": [
58+
"time par for 0.205038 sec\n"
59+
]
60+
}
61+
],
62+
"source": [
63+
"with timer('par for'):\n",
64+
" sleep(0.2)"
65+
]
66+
},
67+
{
68+
"cell_type": "markdown",
69+
"id": "7f0e1f69",
70+
"metadata": {},
71+
"source": [
72+
"Note that the execution time is printed even if there is an error"
73+
]
74+
},
75+
{
76+
"cell_type": "code",
77+
"execution_count": 26,
78+
"id": "77a696f1",
79+
"metadata": {},
80+
"outputs": [
81+
{
82+
"name": "stdout",
83+
"output_type": "stream",
84+
"text": [
85+
"time non existing file 0.000449 sec\n"
86+
]
87+
},
88+
{
89+
"ename": "FileNotFoundError",
90+
"evalue": "[Errno 2] No such file or directory: 'does_not_exists.md'",
91+
"output_type": "error",
92+
"traceback": [
93+
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
94+
"\u001b[0;31mFileNotFoundError\u001b[0m Traceback (most recent call last)",
95+
"Cell \u001b[0;32mIn[26], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m timer(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mnon existing file\u001b[39m\u001b[38;5;124m'\u001b[39m):\n\u001b[0;32m----> 2\u001b[0m \u001b[38;5;28;43mopen\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mdoes_not_exists.md\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mr\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n",
96+
"File \u001b[0;32m~/opt/anaconda3/lib/python3.9/site-packages/IPython/core/interactiveshell.py:284\u001b[0m, in \u001b[0;36m_modified_open\u001b[0;34m(file, *args, **kwargs)\u001b[0m\n\u001b[1;32m 277\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m file \u001b[38;5;129;01min\u001b[39;00m {\u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m2\u001b[39m}:\n\u001b[1;32m 278\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m 279\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mIPython won\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mt let you open fd=\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mfile\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m by default \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 280\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mas it is likely to crash IPython. If you know what you are doing, \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 281\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124myou can use builtins\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m open.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 282\u001b[0m )\n\u001b[0;32m--> 284\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mio_open\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfile\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n",
97+
"\u001b[0;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: 'does_not_exists.md'"
98+
]
99+
}
100+
],
101+
"source": [
102+
"with timer('non existing file'):\n",
103+
" open(\"does_not_exists.md\", 'r')"
104+
]
105+
},
106+
{
107+
"cell_type": "markdown",
108+
"id": "7cfe5478",
109+
"metadata": {},
110+
"source": [
111+
"THere is another way to create such context manager, which is using contextlib.contextmanager"
112+
]
113+
},
114+
{
115+
"cell_type": "code",
116+
"execution_count": 13,
117+
"id": "5bc668ac",
118+
"metadata": {},
119+
"outputs": [],
120+
"source": [
121+
"from contextlib import contextmanager\n",
122+
"import time\n",
123+
"\n",
124+
"@contextmanager\n",
125+
"def timer(name=''):\n",
126+
" start = time.time()\n",
127+
" yield\n",
128+
" end = time.time()\n",
129+
" print(f\"Time needed for {name}: {end-start} sec\")"
130+
]
131+
},
132+
{
133+
"cell_type": "code",
134+
"execution_count": 14,
135+
"id": "22a71fe3",
136+
"metadata": {},
137+
"outputs": [
138+
{
139+
"name": "stdout",
140+
"output_type": "stream",
141+
"text": [
142+
"Time needed for sum: 3.0994415283203125e-06 sec\n"
143+
]
144+
}
145+
],
146+
"source": [
147+
"import requests\n",
148+
"\n",
149+
"with timer('sum'):\n",
150+
" 2*3"
151+
]
152+
}
153+
],
154+
"metadata": {
155+
"kernelspec": {
156+
"display_name": "Python 3 (ipykernel)",
157+
"language": "python",
158+
"name": "python3"
159+
},
160+
"language_info": {
161+
"codemirror_mode": {
162+
"name": "ipython",
163+
"version": 3
164+
},
165+
"file_extension": ".py",
166+
"mimetype": "text/x-python",
167+
"name": "python",
168+
"nbconvert_exporter": "python",
169+
"pygments_lexer": "ipython3",
170+
"version": "3.9.12"
171+
}
172+
},
173+
"nbformat": 4,
174+
"nbformat_minor": 5
175+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# `01_context_manager_timer`
2+
3+
4+
## How to create a context manager
5+
6+
A context manager is a class that needs to have at least two methods:
7+
8+
- **`__enter__`**: executed when the interpreter enters the context block.
9+
10+
11+
- **`__exit__`**: executed allways either after the last line in the context block OR if an error happens.
12+
13+
14+
### Example: Context manager to print execution time
15+
16+
Let us create a context manager that tells us the execution time of the code within it.
17+
18+
To make it more useful let us print also a user defined string to faciliate knowing what we are timing, in the event we want to time more than one line in a piece of code.
19+
20+
21+
```python
22+
import time
23+
from time import sleep
24+
25+
class timer():
26+
27+
def __init__(self, name = ''):
28+
self.start = time.time()
29+
self.name = name
30+
31+
def __enter__(self):
32+
pass
33+
34+
def __exit__(self, *args):
35+
print(f'time {self.name} {round(time.time() - self.start,6)} sec')
36+
```
37+
38+
Let us use the context manager to time how long does it take to run `sleep(0.2)`
39+
40+
```python
41+
with timer('par for'):
42+
sleep(0.2)
43+
```
44+
45+
time par for 0.205038 sec
46+
47+
48+
Note that the execution time is printed even if there is an error
49+
50+
51+
```python
52+
with timer('non existing file'):
53+
open("does_not_exists.md", 'r')
54+
```
55+
56+
time non existing file 0.000449 sec
57+
58+
59+
60+
---------------------------------------------------------------------------
61+
62+
FileNotFoundError Traceback (most recent call last)
63+
64+
Cell In[26], line 2
65+
1 with timer('non existing file'):
66+
----> 2 open("does_not_exists.md", 'r')
67+
68+
69+
File ~/opt/anaconda3/lib/python3.9/site-packages/IPython/core/interactiveshell.py:284, in _modified_open(file, *args, **kwargs)
70+
277 if file in {0, 1, 2}:
71+
278 raise ValueError(
72+
279 f"IPython won't let you open fd={file} by default "
73+
280 "as it is likely to crash IPython. If you know what you are doing, "
74+
281 "you can use builtins' open."
75+
282 )
76+
--> 284 return io_open(file, *args, **kwargs)
77+
78+
79+
FileNotFoundError: [Errno 2] No such file or directory: 'does_not_exists.md'
80+
81+
82+
THere is another way to create such context manager, which is using contextlib.contextmanager
83+
84+
85+
```python
86+
from contextlib import contextmanager
87+
import time
88+
89+
@contextmanager
90+
def timer(name=''):
91+
start = time.time()
92+
yield
93+
end = time.time()
94+
print(f"Time needed for {name}: {end-start} sec")
95+
```
96+
97+
98+
```python
99+
import requests
100+
101+
with timer('sum'):
102+
2*3
103+
```
104+
105+
Time needed for sum: 3.0994415283203125e-06 sec
106+

0 commit comments

Comments
 (0)