Управление ресурсами : В любом языке программирования очень часто используются такие ресурсы, как файловые операции или подключения к базе данных. Но эти ресурсы ограничены в поставках. Поэтому основная проблема заключается в том, чтобы освободить эти ресурсы после использования. Если они не будут выпущены, это приведет к утечке ресурсов и может привести к замедлению или сбою системы. Было бы очень полезно, если бы у пользователя был механизм автоматической настройки и удаления ресурсов.В Python это может быть достигнуто за счет использования контекстных менеджеров, которые облегчают правильную обработку ресурсов. Наиболее распространенным способом выполнения файловых операций является использование с ключевым словом, как показано ниже:
# Python program showing
# a use of with keyword
with open("test.txt") as f:
data = f.read()
Давайте возьмем пример управления файлами. При открытии файла используется файловый дескриптор, который является ограниченным ресурсом. Только определенное количество файлов может быть открыто процессом одновременно. Это демонстрирует следующая программа.
file_descriptors = []
for x in range(100000):
file_descriptors.append(open('test.txt', 'w'))
Выход:
Traceback (most recent call last):
File "context.py", line 3, in
OSError: [Errno 24] Too many open files: 'test.txt'
Появилось сообщение об ошибке, в котором говорится, что открыто слишком много файлов. Приведенный выше пример представляет собой случай утечки файлового дескриптора. Это происходит потому, что слишком много открытых файлов, и они не закрыты. Могут возникнуть ситуации, когда программист может забыть закрыть открытый файл.
Управление ресурсами с помощью контекстного менеджера :
Предположим, что блок кода вызывает исключение или если он имеет сложный алгоритм с несколькими путями возврата, становится неудобно закрывать файл во всех местах.
Как правило, на других языках при работе с файлами try-except-finally используется для обеспечения закрытия файлового ресурса после использования, даже если есть исключение.Python предоставляет простой способ управления ресурсами: Контекстные менеджеры. Используется ключевое слово with. Когда он будет оценен, он должен привести к объекту, который выполняет управление контекстом. Контекстные менеджеры могут быть написаны с использованием классов или функций(с помощью декораторов).
Создание контекстного менеджера :
При создании контекстных менеджеров с использованием классов пользователю необходимо убедиться, что у класса есть методы: __enter__() and __exit__(). The __enter__() returns возвращает ресурс, которым необходимо управлять, а __exit__() ничего не возвращает, но выполняет операции очистки.
Во — первых, давайте создадим простой класс под названием Контекст менеджер чтобы понять основную структуру создания контекстных менеджеров с помощью классов, как показано ниже:
# Python program creating a
# context manager
class ContextManager():
def __init__(self):
print('init method called')
def __enter__(self):
print('enter method called')
return self
def __exit__(self, exc_type, exc_value, exc_traceback):
print('exit method called')
with ContextManager() as manager:
print('with statement block')
Выход:
init method called
enter method called
with statement block
exit method called
В этом случае создается объект ContextManager. Это присваивается переменной после ключевого слова as, т. е. менеджеру. При запуске вышеуказанной программы последовательно выполняются следующие действия:
- __init__()
- __enter__()
- statement body (код внутри блока with)
- __exit__() [параметры в этом методе используются для управления исключениями]
Управление файлами с помощью контекстного менеджера :
Давайте применим приведенную выше концепцию для создания класса, который помогает в управлении файловыми ресурсами.Класс FileManager помогает открывать файл, записывать/считывать содержимое и затем закрывать его.
# Python program showing
# file management using
# context manager
class FileManager():
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
self.file = None
def __enter__(self):
self.file = open(self.filename, self.mode)
return self.file
def __exit__(self, exc_type, exc_value, exc_traceback):
self.file.close()
# loading a file
with FileManager('test.txt', 'w') as f:
f.write('Test')
print(f.closed)
Выход:
True
Управление файлами с помощью контекстного менеджера и с помощью инструкции :
При выполнении с блок, следующие операции выполняются последовательно:
- A Файловый менеджер объект создается с помощью test.txt в качестве имени файла и w(запись) в качестве режима при выполнении метода __init__.
- Метод __enter__ открывает test.txt файл в режиме записи(операция установки) и возвращает Файловый менеджер объект к переменной f.
- Текст » Test’ записывается в файл.
- Метод __exit__ позаботится о закрытии файла при выходе из с блоком(операция демонтажа).
Когда печать(f.закрыто) выполняется, вывод является Правда в качестве Файловый менеджер уже позаботился о закрытии файла, что в противном случае необходимо было сделать явно.
Управление подключениями к базе данных с помощью контекстного диспетчера :
Давайте создадим простую систему управления подключениями к базе данных. Количество подключений к базе данных, которые могут быть открыты одновременно, также ограничено(как и файловые дескрипторы). Поэтому контекстные менеджеры полезны при управлении подключениями к базе данных, так как может быть вероятность того, что программист может забыть закрыть соединение.
# Python program shows the
# connection management
# for MongoDB
from pymongo import MongoClient
class MongoDBConnectionManager():
def __init__(self, hostname, port):
self.hostname = hostname
self.port = port
self.connection = None
def __enter__(self):
self.connection = MongoClient(self.hostname, self.port)
return self
def __exit__(self, exc_type, exc_value, exc_traceback):
self.connection.close()
# connecting with a localhost
with MongoDBConnectionManager('localhost', '27017') as mongo:
collection = mongo.connection.SampleDb.test
data = collection.find({'_id': 1})
print(data.get('name'))
Управление подключениями к базе данных с помощью контекстного диспетчера и оператора with :
При выполнении с блок, следующие операции выполняются последовательно:
- A MongoDBConnectionManager объект создается с помощью localhost в качестве имени хоста и 27017 в качестве порта при выполнении метода __init__.
- Метод __enter__ открывает соединение mongodb и возвращает Объект MongoDBConnectionManager в переменную монго.
- Осуществляется доступ к тестовой коллекции в базе данных SampleDb, и документ с _id=1. Будет напечатано поле » Имя » документа.
- Метод __exit__ позаботится о закрытии соединения при выходе из с блок(операция демонтажа).