Python standard module-usage of ContextManager context Manager,

Source: Internet
Author: User

Python standard module-usage of ContextManager context Manager,

When writing code, we want to put some operations into a code block so that the code block can be executed in a certain running state, and another operation will be executed when the code block is left, end the current status. In short, the context manager is used to specify the scope of use of the object. If the range is exceeded, it is processed ".

This feature was introduced after Python2.5. Its advantage is that it makes your code more readable and error-prone.

1 module Introduction

Several years ago, Python 2.5 added a very special keyword,. The with statement allows developers to create a context manager. What is the context manager? The context Manager allows you to start and end events automatically. For example, you may want to open a file, write some content, and close the file. This is perhaps the most classic example in the context manager. In fact, when you use the with statement to open a file, Python automatically creates a context manager for you.

with open("test/test.txt","w") as f_obj:  f_obj.write("hello")

If you are using Python 2.4, You have to complete this task in an old way.

f_obj = open("test/test.txt","w")f_obj.write("hello")f_obj.close()

The working mechanism behind the context manager is to use the following Python Methods: __enter _ and _ exit __. Let's try to create our context manager to understand how the context Manager works.

2 module usage

2.1 create a context manager class

Instead of continuing to use Python to open a file, we should create a context manager, which will create an SQLite database connection. When the task is completed, it will be closed. The following is a simple example.

import sqlite3class DataConn:  def __init__(self,db_name):    self.db_name = db_name  def __enter__(self):    self.conn = sqlite3.connect(self.db_name)    return self.conn  def __exit__(self,exc_type,exc_val,exc_tb):    self.conn.close()    if exc_val:      raiseif __name__ == "__main__":  db = "test/test.db"  with DataConn(db) as conn:    cursor = conn.cursor()

In the above Code, we created a class to obtain the path of the SQLite database file. The _ enter _ method is automatically executed and the database connection object is returned. Now we have obtained the database connection object, and then we create a cursor to write data to the database or query the database. When we exit the with statement, it will call the _ exit _ method to execute and close the connection.

Let's use other methods to create the context manager.

2.2 Use contextlib to create a context Manager

Python 2.5 not only adds the with statement, but also the contextlib module. This allows us to use the contextmanager function of contextlib as the decorator to create a context manager. Let's try to use it to create a context manager for opening and closing files.

from contextlib import contextmanager@contextmanagerdef file_open(path):  try:    f_obj = open(path,"w")    yield f_obj  except OSError:    print("We had an error!")  finally:    print("Closing file")    f_obj.close()if __name__ == "__main__":  with file_open("test/test.txt") as fobj:    fobj.write("Testing context managers")

Here, we introduce contextmanager from the contextlib module, and then describe the defined file_open function. This allows us to use the with statement of Python to call the file_open function. In the function, we open the file and pass it out through yield. In the end, the main function can use it.

Once the with statement ends, the control will return to the file_open function, which continues to execute the Code following the yield statement. This will eventually execute the finally statement -- close the file. If we encounter an OSError error when opening the file, it will be captured, and the finally statement will still close the file handle.

Contextlib. closing (thing)

The contextlib module provides some convenient tools. The first tool is the closing class. Once the code block is run, it will close the event. The official Python documentation provides an example similar to the following,

>>> from contextlib import contextmanager>>> @contextmanager... def closing(db):...   try:...     yield db.conn()...   finally:...     db.close()

In this Code, we have created a function that is enclosed in contextmanager. This is the same as the closing class. The difference is that we can use the closing class itself in the with statement, rather than the decorator. Let's take a look at the following example,

>>> from contextlib import closing>>> from urllib.request import urlopen>>> with closing(urlopen("http://www.google.com")) as webpage:...   for line in webpage:...     pass

In this example, we open a url webpage in the closing class. Once the with statement is run, the handle pointing to the webpage is closed.

Contextlib. suppress (* exceptions)

Another tool is the suppress class added to Python 3.4. The idea behind this context management tool is that it can prohibit any number of exceptions. Suppose we want to ignore the FileNotFoundError exception. If you write the following context manager, it will not run normally.

>>> with open("1.txt") as fobj:...   for line in fobj:...     print(line)...Traceback (most recent call last): File "<stdin>", line 1, in <module>FileNotFoundError: [Errno 2] No such file or directory: '1.txt'

As you can see, the context manager does not handle this exception. If you want to ignore this error, you can do it as follows,

>>> from contextlib import suppress>>> with suppress(FileNotFoundError):...   with open("1.txt") as fobj:...     for line in fobj:...       print(line)

In this Code, we introduce suppress and pass the exception we want to ignore to it. In this example, FileNotFoundError is used. If you want to run this code, you will notice that when the file does not exist, nothing happens and no errors are thrown. Note that this context manager is reusable and will be explained in Chapter 2.4.

Contextlib. redirect_stdout/redirect_stderr

The contextlib module also has a pair of tools for redirecting standard output and standard error output, which are added to Python 3.4 and 3.5 respectively. Before these tools are added, if you want to redirect standard output, perform the following operations,

import syspath = "test/test.txt"with open(path,"w") as fobj:  sys.stdout = fobj  help(sum)

Using the contextlib module, you can perform the following operations,

from contextlib import redirect_stdoutpath = "test/test.txt"with open(path,"w") as fobj:  with redirect_stdout(fobj):    help(redirect_stdout)

In the preceding two examples, we redirect the standard output to a file. When we call the help function of Python, the information is not output to the standard output, but saved to the redirected file. You can also redirect the standard output to the cache or to the file control type obtained from interfaces such as Tkinter or wxPython.

2.3 ExitStack

ExitStack is a context manager that allows you to easily combine or clear with other context management. This sounds a bit confusing. Let's look at an official Python document example, which may make it easier for us to understand.

>>> from contextlib import ExitStack>>> filenames = ["1.txt","2.txt"]>>> with ExitStack as stack:...   file_objects = [stack.enter_context(open(filename)) for filename in filenames]

This Code creates a series of context managers in the list. ExitStack maintains a register stack. When we exit the with statement, the file will be closed, and the stack will call these context managers in reverse order.

There are many examples of contextlib In the Python official documentation. You can learn the following technical points:

  1. Capture exceptions from the _ enter _ Method
  2. Supports variable number of context managers
  3. Replace try-finally
  4. Others

2.4 reusable context Manager

Most of the context managers you create can only be used once in the with statement, for example:

>>> from contextlib import contextmanager>>> @contextmanager... def single():...   print("Yielding")...   yield...   print("Exiting context manager")...>>> context = single()>>> with context:...   pass...YieldingExiting context manager>>> with context:...   pass...Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python3.4/contextlib.py", line 61, in __enter__  raise RuntimeError("generator didn't yield") from NoneRuntimeError: generator didn't yield

In this Code, we created a context manager instance and tried to run the with statement twice in Python. During the second operation, it throws a RuntimeError.

But what if we want to run the context manager twice? We need to use reusable context manager. Let's use the previously used redirect_stdout context manager as an example,

>>> from contextlib import redirect_stdout>>> from io import StringIO>>> stream = StringIO()>>> write_to_stream = redirect_stdout(stream)>>> with write_to_stream:...   print("Write something to the stream")...   with write_to_stream:...     print("Write something else to stream")...>>> print(stream.getvalue())Write something to the streamWrite something else to stream

In this Code, we created a context manager that writes data to StringIO (a file stream in memory. This code runs normally without throwing a RuntimeError as before, because redirect_stdout is reusable and can be called twice. Of course, there will be more function calls in actual examples, which will be more complicated. Note that reusable context managers are not necessarily thread-safe. If you need to use it in a thread, read the Python documentation carefully.

2.5 Conclusion

The context manager is interesting and convenient. I often use them in automated testing, such as opening and closing conversations. Now, you should be able to use Python's built-in tools to create your context manager. You can continue to read the Python documentation on contextlib, which contains a lot of knowledge not covered in this article.

The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.