Skip to content

Commit 47de9c2

Browse files
committed
closes yasoob#88 Thanks @JoshMcCullough
1 parent 6036232 commit 47de9c2

1 file changed

Lines changed: 32 additions & 33 deletions

File tree

context_managers.rst

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Context managers
1+
Context Managers
22
----------------
33

44
Context managers allow you to allocate and release resources precisely
@@ -30,16 +30,16 @@ advantage of using a ``with`` statement is that it makes sure our file
3030
is closed without paying attention to how the nested block exits.
3131

3232
A common use case of context managers is locking and unlocking resources
33-
and closing opened files (as I have already showed you).
33+
and closing opened files (as I have already shown you).
3434

35-
Let's see how we can implement our own Context Manager. This would allow
35+
Let's see how we can implement our own Context Manager. This should allow
3636
us to understand exactly what's going on behind the scenes.
3737

38-
Implementing Context Manager as a Class:
38+
Implementing a Context Manager as a Class:
3939
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4040

4141
At the very least a context manager has an ``__enter__`` and
42-
``__exit__`` methods defined. Let's make our own file opening Context
42+
``__exit__`` method defined. Let's make our own file-opening Context
4343
Manager and learn the basics.
4444

4545
.. code:: python
@@ -52,28 +52,28 @@ Manager and learn the basics.
5252
def __exit__(self, type, value, traceback):
5353
self.file_obj.close()
5454
55-
Just by defining ``__enter__`` and ``__exit__`` methods we can use it in
55+
Just by defining ``__enter__`` and ``__exit__`` methods we can use our new class in
5656
a ``with`` statement. Let's try:
5757

5858
.. code:: python
5959
6060
with File('demo.txt', 'w') as opened_file:
6161
opened_file.write('Hola!')
6262
63-
Our ``__exit__`` function accepts three arguments. They are required by
63+
Our ``__exit__`` method accepts three arguments. They are required by
6464
every ``__exit__`` method which is a part of a Context Manager class.
6565
Let's talk about what happens under-the-hood.
6666

67-
1. The ``with`` statement stores the ``__exit__`` method of ``File``
67+
1. The ``with`` statement stores the ``__exit__`` method of the ``File``
6868
class.
69-
2. It calls the ``__enter__`` method of ``File`` class.
70-
3. ``__enter__`` method opens the file and returns it.
71-
4. the opened file handle is passed to ``opened_file``.
72-
5. we write to the file using ``.write()``
73-
6. ``with`` statement calls the stored ``__exit__`` method.
74-
7. the ``__exit__`` method closes the file.
75-
76-
Handling exceptions
69+
2. It calls the ``__enter__`` method of the ``File`` class.
70+
3. The ``__enter__`` method opens the file and returns it.
71+
4. The opened file handle is passed to ``opened_file``.
72+
5. We write to the file using ``.write()``.
73+
6. The ``with`` statement calls the stored ``__exit__`` method.
74+
7. The ``__exit__`` method closes the file.
75+
76+
Handling Exceptions
7777
^^^^^^^^^^^^^^^^^^^
7878

7979
We did not talk about the ``type``, ``value`` and ``traceback``
@@ -92,20 +92,20 @@ instance:
9292
with File('demo.txt', 'w') as opened_file:
9393
opened_file.undefined_function('Hola!')
9494
95-
Let's list down the steps which are taken by the ``with`` statement when
96-
an error is encountered.
95+
Let's list the steps which are taken by the ``with`` statement when
96+
an error is encountered:
9797

9898
1. It passes the type, value and traceback of the error to the
9999
``__exit__`` method.
100100
2. It allows the ``__exit__`` method to handle the exception.
101-
3. If ``__exit__`` returns True then the exception was gracefully
101+
3. If ``__exit__`` returns ``True`` then the exception was gracefully
102102
handled.
103-
4. If anything other than True is returned by the ``__exit__`` method then
104-
an exception is raised by the ``with`` statement.
103+
4. If anything other than ``True`` is returned by the ``__exit__`` method then
104+
the exception is raised by the ``with`` statement.
105105

106106
In our case the ``__exit__`` method returns ``None`` (when no return
107-
statement is encountered then the method returns ``None``). Therefore, the
108-
``with`` statement raises the exception.
107+
statement is encountered then the method returns ``None``). Therefore,
108+
the ``with`` statement raises the exception:
109109

110110
.. code:: python
111111
@@ -132,11 +132,11 @@ Let's try handling the exception in the ``__exit__`` method:
132132
133133
# Output: Exception has been handled
134134
135-
Our ``__exit__`` method returned True, therefore no exception was raised
135+
Our ``__exit__`` method returned ``True``, therefore no exception was raised
136136
by the ``with`` statement.
137137

138-
This is not the only way to implement context managers. There is another
139-
way and we will be looking at it in this next section.
138+
This is not the only way to implement Context Managers. There is another
139+
way and we will be looking at it in the next section.
140140

141141
Implementing a Context Manager as a Generator
142142
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -156,9 +156,9 @@ Let's see a basic, useless example:
156156
yield f
157157
f.close()
158158
159-
Okay! This way of implementing Context Managers appears to be more
159+
Okay! This way of implementing Context Managers appear to be more
160160
intuitive and easy. However, this method requires some knowledge about
161-
generators, yield, and decorators. In this example we have not caught any
161+
generators, yield and decorators. In this example we have not caught any
162162
exceptions which might occur. It works in mostly the same way as the
163163
previous method.
164164

@@ -167,11 +167,11 @@ Let's dissect this method a little.
167167
1. Python encounters the ``yield`` keyword. Due to this it creates a
168168
generator instead of a normal function.
169169
2. Due to the decoration, contextmanager is called with the function
170-
name (open\_file) as it's argument.
171-
3. The ``contextmanager`` function returns the generator wrapped by the
170+
name (``open\_file``) as it's argument.
171+
3. The ``contextmanager`` decorator returns the generator wrapped by the
172172
``GeneratorContextManager`` object.
173173
4. The ``GeneratorContextManager`` is assigned to the ``open_file``
174-
function. Therefore, when we later call ``open_file`` function, we
174+
function. Therefore, when we later call the ``open_file`` function, we
175175
are actually calling the ``GeneratorContextManager`` object.
176176

177177
So now that we know all this, we can use the newly generated Context
@@ -180,5 +180,4 @@ Manager like this:
180180
.. code:: python
181181
182182
with open_file('some_file') as f:
183-
f.write('hola!')
184-
183+
f.write('hola!')

0 commit comments

Comments
 (0)