Python中的上下文管理器
在本教程中,我们将了解Python中的”上下文管理器”以及它在管理资源、文件描述符和数据库连接方面的帮助。
管理资源:
用户在任何编程语言中都常常使用资源,如文件操作或数据库连接。
但是所有这些资源都有限制。因此,主要问题是确保这些资源在使用后能够释放。
因为如果它们没有被释放,这可能导致资源泄漏,从而可能导致系统变慢或崩溃。如果机器被设置在用户系统中,可以自动清除资源,这将非常有帮助。在Python中,用户可以通过使用上下文管理器实现这一点,上下文管理器用于方便地处理资源。执行文件操作的最流行的方法就是在Python中使用”with”关键字。
示例1:
with open("text_file.txt") as file:
data = file.read()
让我们来看一个文件管理的示例。当一个文件被打开时,文件描述符就会被消耗掉,而这是一种有限资源。进程一次只能打开有限数量的文件。
示例2:
file_descriptors = []
for Y in range(10000):
file_descriptors.append( open ('test_file.txt', 'w'))
输出:
OSError Traceback (most recent call last)
in
1 file_descriptors = []
2 for Y in range(10000):
----> 3 file_descriptors.append( open ('test_file.txt', 'w'))
OSError: [Errno 24] Too many open files: 'test_file.txt'
上面的示例是文件描述符泄露的情况。出现了一个错误,提示”Too many open files”。这是因为有太多的打开文件,而且它们没有关闭。可能会有一种情况,用户可能忘记关闭打开的文件。
如何使用上下文管理器管理资源
如果程序块引发异常或有任何复杂算法具有多条返回路径,关闭文件的所有位置都是困难的。
大多数情况下,用户在使用文件时使用其他编程语言中的”try-except-finally”来确保文件资源在使用后关闭,即使有异常。但在Python中,他们可以使用”上下文管理器”来管理资源。用户可以使用”with”关键字。当它被评估时,它将产生一个可以执行上下文管理的对象。我们可以使用类或使用装饰器的函数来编写上下文管理器。
如何创建上下文管理器:
当用户创建一个上下文管理器时,他们需要确保该类具有以下方法:enter() 和 exit()。
enter()方法将返回要管理的资源。
exit()方法不会返回任何内容,但会执行清理操作。
让我们来看一个示例:
- 首先,我们将创建一个简单的名为”context_manager”的类,以了解使用类方法创建上下文管理器的基本结构。
示例:
class context_manager():
def __init__(self):
print ("The 'init' method is called")
def __enter__(self):
print ("The 'enter' method is called")
return self
def __exit__(self, exc_type, exc_value, exc_traceback):
print ("The 'exit' method is called")
with context_manager() as manager:
print ("The 'with' statement is block")
输出
The 'init' method is called
The 'enter' method is called
The 'with' statement is block
The 'exit' method is called
示例
在上面的代码中,我们创建了“context_manager”对象。在“as”关键字之后,将其分配给变量manager。运行程序后,按照以下顺序执行了以下方法:
- int()
- enter()
- 语句体,即“with”语句块内部的代码。
- exit(),在此方法中,参数用于管理异常。
使用上下文管理器进行文件管理
现在,我们将应用上述概念来创建一个类,该类可以帮助管理文件资源。 “file_manager”类将帮助打开文件,读取或写入内容,然后关闭文件。
示例:
class file_manager():
def __init__(self, file_name, mode):
self.filename = file_name
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()
# At last, load the file
with file_manager('test_file.txt', 'w') as file:
file.write('JavaTpoint')
print (file.closed)
输出:
True
如何使用上下文管理器和”with”语句进行文件管理
用户执行”with”语句块后,操作将按以下顺序执行:
- 将以”文本文件.txt”作为文件名,以”w”(写入)作为模式创建”file_manager”对象并执行init()方法。
- enter()方法将以写入模式打开”文本文件.txt”并将”file_manager”对象返回给变量”file”。
- 将文本”JavaTpoint”写入文件中。
- exit()方法将负责在退出”with”语句块后关闭文件,这是清理操作。当运行”print (file.closed)”语句时,用户将得到输出”True”,因为”file_manager”已经关闭了文件,否则需要显式关闭文件。
如何使用上下文管理器管理数据库连接
现在,我们将展示如何创建一个简单的数据库连接管理系统。与文件描述符一样,同时打开数据库连接的数量是有限的。因此,我们使用上下文管理器,因为它有助于管理对数据库的连接,用户可能会忘记关闭连接。
安装pymongo:
要通过上下文管理器管理数据库连接,用户首先必须使用以下命令安装”pymongo”库:
!pip3 instal pymongo
示例:
from pymongo import MongoClient as moc
class mongo_db_connection_manager():
def __init__(self, host_name, port = '27017'):
self.hostname = host_name
self.port = port
self.connection = None
def __enter__(self):
self.connection = moc(self.hostname, self.port)
return self
def __exit__(self, exc_type, exc_value, exc_traceback):
self.connection.close()
# Now, connect with a localhost
with mongo_db_connection_manager('localhost', 27017) as mongo:
collection_1 = mongo.connection.SampleDb.test
data_1 = collection_1.find({'_id': 142})
print (data_1.get(name))
输出:
Test
解释:
在上述代码中,在执行完“with”语句块之后,以下操作将按顺序发生。
- “mongo_db_connection_manager”对象将使用“localhost”作为“host_name”,端口等于“27017”创建,当执行init()方法时。
- enter()方法将打开“mongodb”连接,并将“mongo_db_connection_manager”对象返回给变量“mongo”。
- “SampleDB”数据库将访问“test”连接,并检索“_id = 147”的文档。将打印文档的name字段。
- exit()方法将在退出“with”语句块后处理文件关闭操作,即拆卸操作。
总结
在本教程中,我们讨论了Python中的内容管理器,如何创建内容管理器以及它如何帮助资源管理、文件管理和管理数据库连接。