1- Context managers
1+ Context Managers
22----------------
33
44Context 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
3030is closed without paying attention to how the nested block exits.
3131
3232A 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
3636us 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
4141At 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
4343Manager 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
5656a ``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
6464every ``__exit__ `` method which is a part of a Context Manager class.
6565Let'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
7979We 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
98981. It passes the type, value and traceback of the error to the
9999 ``__exit__ `` method.
1001002. 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
106106In 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
136136by 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
141141Implementing 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
160160intuitive 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
162162exceptions which might occur. It works in mostly the same way as the
163163previous method.
164164
@@ -167,11 +167,11 @@ Let's dissect this method a little.
1671671. Python encounters the ``yield `` keyword. Due to this it creates a
168168 generator instead of a normal function.
1691692. 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.
1731734. 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
177177So 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