Python Context Manager Content Manager

  • 2021-11-13 08:08:14
  • OfStack

In Python, we often hear about the context manager (Context Manager), so let's discuss what this is and what it does.

Among the context managers in Python, with is the most used to open files, and after leaving the statements contained in with, one task similar to cleaning will be performed, such as closing files and closing connection objects.

Practice

In code practice, we ignore that in the same code fragment, we first open the file and then directly do other processing on the file, because it makes no sense and the resources are occupied.

Let's look at the code detected below:


#!/usr/bin/env python
# _*_ coding: UTF-8 _*_
# MedusaSorcerer Script
import os


class OpenFile:
    def __init__(self):
        self.file = None

    def open(self, path):
        self.file = open(path, 'w')


if __name__ == '__main__':
    file_path = 'medusa.md'
    file = OpenFile()
    file.open(file_path)
    os.remove(file_path)

In the code, we refer to the file object in the way of instance attribute. After that, we use os module to delete the written file. After you modify the code snippet, the following will appear:

Traceback (most recent call last):
File "medusa/main.py", line 19, in < module >
os.remove(file_path)
PermissionError: [WinError 32] This file is in use by another program and cannot be accessed by the process. : 'medusa. md'

Process finished with exit code 1

That's because the deleted file has not been released by resources. The way we apply functions based on the above:


#!/usr/bin/env python
# _*_ coding: UTF-8 _*_
# MedusaSorcerer Script
import os


class OpenFile:
    def __init__(self):
        self.file = None

    def open(self, path):
        self.file = open(path, 'w')


def open_file(path):
    file = OpenFile()
    file.open(path)


if __name__ == '__main__':
    file_path = 'medusa.md'
    open_file(file_path)
    os.remove(file_path)

This code will be executed successfully, because when you execute the function, the temporary variables in the function will be recycled and released, so the instance object of OpenFile will be released, and the instance attribute will not exist and be released, so the execution will be successful.

Should all our operations be performed in the form of function wrapping? The emergence of with perfectly solves this problem:


#!/usr/bin/env python
# _*_ coding: UTF-8 _*_
# MedusaSorcerer Script
import os

if __name__ == '__main__':
    file_path = 'medusa.md'
    with open(file_path, 'w') as f:
        print(f)
    os.remove(file_path)

In with syntax, the following operation of opening a file and the returned file object are assigned to f variable, the contents of f variable are output in the structure, and the file is deleted outside the structure:

medusa\python.exe medusa/main.py
< _io.TextIOWrapper name='medusa.md' mode='w' encoding='cp936' >

Process finished with exit code 0

You can still delete files without using close (), which is the beauty of context management.

Realization

Context management, which actually implements the __enter__ and __exit__ methods:


#!/usr/bin/env python
# _*_ coding: UTF-8 _*_
# MedusaSorcerer Script


class Medusa:

    def __init__(self):
        print('__init__')

    def __enter__(self):
        print('__enter__')

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('__exit__')


if __name__ == '__main__':
    medusa = Medusa()
    with medusa:
        print('with object')
    print('finish')

Here is the output:

__init__
__enter__
with object
__exit__
finish

We find that magic methods are automatically scheduled when combined with some syntax, so in context management, some objects are closed in automatic scheduling.

Advantages

Implementing context management can simplify our code, make it easier to read, and do all the work with the least amount of code.


Related articles: