Heim >Backend-Entwicklung >Python-Tutorial >Python-Programmierung: Context Manager leicht verstehen (Context Manager)

Python-Programmierung: Context Manager leicht verstehen (Context Manager)

PHPz
PHPznach vorne
2023-04-12 14:07:132340Durchsuche

Vorwort

Dieser Artikel konzentriert sich auf die Erklärung und Anwendung des Python-Kontextmanagements. Oder durch Codebeispiele, vergleichendes Verständnis und Lernen, um das Verständnis, die Beherrschung und die Anwendung von „mehr Geschwindigkeit, bessere Wirtschaftlichkeit“ zu erreichen. Fangen wir ohne weiteres an –

1 Was ist ein Kontextmanager? Ein Kontextmanager ist ein Objekt, das den Laufzeitkontext definiert, der beim Ausführen einer with-Anweisung eingerichtet werden soll. Ein Kontextmanager ist eine Laufzeitumgebung, die den Ein- und Ausstieg für den Kontext, in dem ein Codeblock ausgeführt wird, automatisch verwaltet. Kontextmanager werden normalerweise mit einer with-Anweisung aufgerufen, können aber auch durch direkten Aufruf ihrer Methoden verwendet werden.

Zu den typischen Anwendungen von Kontextmanagern gehören das Speichern und Wiederherstellen verschiedener globaler Zustände, das Sperren und Entsperren von Ressourcen, das Schließen geöffneter Dateien und mehr.

In diesem Kapitel erfahren Sie, wie Sie Kontextmanager in Python verwenden und wie Sie Kontextmanager anpassen.

1.With-Anweisung

with-Anweisung wird für die Ausführung von Methoden-Wrapper-Blöcken verwendet, die vom Kontextmanager definiert werden. Dadurch kann das allgemeine Verwendungsmuster „try...except...finally“ für eine einfache Wiederverwendung gekapselt werden. Die with-Anweisung stellt im Vergleich zum herkömmlichen try...exclus...finally-Block kürzeren und wiederverwendbaren Code bereit.

In der Python-Standardbibliothek unterstützen viele Klassen die with-Anweisung. Ein sehr häufiges Beispiel ist die integrierte Funktion open(), die ein Muster für die Verarbeitung von Dateiobjekten mithilfe der with-Anweisung bereitstellt.

Das Folgende ist die allgemeine Syntax der with-Anweisung:

with expression as target:
# 使用target
# 来处理事情

Sehen wir uns ein Beispiel für die Verwendung der open()-Funktion an. Im Dateiordner des aktuellen Projekts befindet sich eine Textdatei. Der Dateiname lautet color_names.txt und enthält einige Farbnamen (Sie können selbst Textinhalte bereitstellen). Wir möchten den Inhalt dieser Datei öffnen und drucken, indem wir die Funktion open() und die Anweisung with verwenden. Das Codebeispiel lautet wie folgt:

import os
fileDirPath = os.getcwd()+os.sep+"ctxManager"+os.sep #自定义文件路径
# 指定文件路径和名称
path = fileDirPath+'files/color_names.txt'

# with 语句
with open(path, mode='r') as file:
# 读取文件内容
print(file.read())

Die Ausgabe des Programmlaufs sieht wie folgt aus:

red
orange
yellow
green
blue
white
black

In der obigen Liste sehen Sie einen häufigen Anwendungsfall der with-Anweisung. Wir verwenden die Funktion open(), um die Datei im angegebenen Pfad (Pfad) zu öffnen, und die Funktion open() gibt das Dateiobjekt im schreibgeschützten Modus zurück. Der Code verwendet dann dieses Dateiobjekt, um seinen Inhalt über den Code zu lesen und auszudrucken: print(file.read()).

Das obige Beispiel ist eine typische Verwendung des Kontextmanagers. Um Kontextmanager besser zu verstehen und anzuwenden, müssen wir weiterlesen.

3. Context Manager Protocol

Context Manager Protocol ist, um es ganz klar auszudrücken, der Verarbeitungsmechanismus des Kontextmanagers oder der vorgegebene Protokollstandard. Dieser Teil ist auch hier zu finden: Python Core Protocol. Um die Unabhängigkeit beim Lesen zu gewährleisten, sprechen wir hier noch einmal darüber.

Pythons with-Anweisung unterstützt das Konzept des Laufzeitkontexts, der von einem Kontextmanager definiert wird. Dies wird durch ein Methodenpaar erreicht, das es einer benutzerdefinierten Klasse ermöglicht, einen Laufzeitkontext zu definieren, der eingegeben wird, bevor der Anweisungshauptteil ausgeführt wird, und der am Ende der Anweisung beendet wird.

Die zuvor erwähnten Methoden werden Kontextmanagerprotokolle genannt. Schauen wir uns diese beiden Methoden im Detail an:

1) __enter__(self)

Diese Methode wird von der with-Anweisung aufgerufen, um den Laufzeitkontext einzugeben, der sich auf das aktuelle Objekt bezieht. Die with-Anweisung bindet den Rückgabewert dieser Methode an das Ziel (falls vorhanden), das in der as-Klausel der Anweisung angegeben ist.

Der im obigen Beispiel zurückgegebene Kontextmanager ist das Dateiobjekt. Hinter den Kulissen gibt das Dateiobjekt sich selbst von __enter__() zurück, um die Verwendung von open() als kontextbezogenen Ausdruck in einer with-Anweisung zu ermöglichen.

2)__exit__(self, exc_type, exc_value, Traceback):

Diese Methode wird aufgerufen, wenn die Ausführung den With-Codeblock verlässt. Der diesem Objekt zugeordnete Laufzeitkontext wird verlassen. Die Parameter beschreiben die Ausnahmeinformationen, die zum Beenden des Kontexts geführt haben. Wenn der Kontext ohne Ausnahme verlassen wird, sind alle drei Parameter None.

Wenn eine Ausnahme bereitgestellt wird und Sie möchten, dass die Methode die Ausnahme unterdrückt (d. h. verhindert, dass sie weitergegeben wird), sollte sie einen True-Wert zurückgeben. Andernfalls wird die Ausnahme beim Verlassen dieser Methode normal behandelt. Die Methode __exit__() gibt einen booleschen Wert zurück, der True oder False sein kann.

Der Prozess zum Ausführen einer with-Anweisung mithilfe von Methoden im Kontextmanagerprotokoll ist wie folgt:

with EXPRESSION as TARGET:
SUITE

Werten Sie den Kontextausdruck (EXPRESSION) aus, um den Kontextmanager zu erhalten.
  • Laden Sie __enter__() des Kontextmanagers zur späteren Verwendung.
  • Laden Sie den __exit__() des Kontextmanagers zur späteren Verwendung.
  • Rufen Sie die Methode __enter__() des Kontextmanagers auf.
  • Wenn ein TARGET in der with-Anweisung enthalten ist, wird ihm der Rückgabewert von __enter__() zugewiesen.
  • Ausführungssuite (Codeblock im Umfang der with-Anweisung).
  • Rufen Sie die Methode __exit__() des Kontextmanagers auf. Wenn die Ausnahme zum Beenden der Suite geführt hat, werden Typ, Wert und Traceback als Argumente an __exit__() übergeben. Andernfalls werden drei None-Parameter bereitgestellt.
  • Wenn die Suite aus einem anderen Grund als einer Ausnahme beendet wird, wird der Rückgabewert von __exit__() ignoriert und die Ausführung des nachfolgenden Codes (falls vorhanden) wird an der normalen Position für den ausgeführten Exit-Typ fortgesetzt.

4. Klassenformular-Kontextmanager

Da wir nun die Grundidee hinter dem Kontextmanagerprotokoll verstanden haben, implementieren wir es in einer Klasse. Diese Klasse wird unser Kontextmanager sein und wir werden sie später in der with-Anweisung verwenden.

定义的上下文管理器类参考示例清单如下:

# 自定义上下文管理器类
class CustomContextManager:
# 初始化方法init -> 定义一些变量
def __init__(self, path, mode):
self.path = path
self.mode = mode
self.file = None

# __enter__ method -> open the file
def __enter__(self):
self.file = open(self.path, self.mode)
return self.file

# exit method to close the file

def __exit__(self, exc_type, exc_value,exc_traceback):
self.file.close()

我们的CustomContextManager类实现了成为上下文管理器的必要方法:__enter__和__exit__。

在__init__方法中,它定义了三个实例变量来存储路径、模式和文件对象。

在__enter__方法中,它使用内置的open()函数打开指定路径中的文件。由于open()函数返回file对象,我们将其赋值给self.file属性。

在__exit__方法中,我们将文件关闭:self.file.close()。

__exit__方法接受三个参数,它们是上下文管理器协议所需要的。

现在我们可以在with语句中使用自定义上下文管理器。

使用自定义的类上下文管理器的示例(和我们前面的示例雷同):

# 应用示例
import os
fileDirPath = os.getcwd()+os.sep+"ctxManager"+os.sep
# 在with语句中使用自定义上下文管理器
file_path = fileDirPath + 'files/color_names.txt'

with CustomContextManager(path=file_path, mode='r') as file:
#输出文件file内容
print(file.read())

运行输出结果这里不再赘述。简单解释一下代码。

上面清单中,在with语句中使用CustomContexManager类,通过它来读取文件内容并打印出来。下面是这个自定义上下文管理器幕后的故事:

1)在with行,调用类CustomContextManager的方_enter__法

2) __enter__方法打开文件并返回它。

3)我们将打开的文件简单地命名为file。

4)在with语句块中,读取文件内容并将其打印出来。

5)with语句自动调用__exit__方法。

6)__exit__方法关闭文件。

我们再来定义另一个上下文管理器类。这次我们想打印指定文件夹中的文件列表。

参考实现的代码清单如下:

class ContentList:
'''Prints the content of a directory'''

def __init__(self, directory):
self.directory = directory

def __enter__(self):
return os.listdir(self.directory)

def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is not None:
print("Error getting directory list.")
return True

# 输出项目目录下的内容
project_directory = '.'
with ContentList(project_directory) as directory_list:
print(directory_list)

在代码清单中,我们定义了一个新的上下文管理器。这个类的名字是ContentList。为什么它是一个上下文管理器?因为它实现了上下文管理器协议(__enter__和__exit__方法)。

我们将目录路径作为类构造函数__init__方法中的参数。

在__enter__方法中,只需调用os模块中的listdir()方法,就可以获得该目录中的内容列表:os.listdir(self.directory)。然后返回这个列表。请注意,在这个上下文管理器中我们的__enter__方法返回一个列表。

在__exit__方法中,我们检查是否存在任何错误。如果我们的上下文管理器中有错误,exc_type、exc_val、exc_tb参数值将不会为None。因此,我们检查exc_type是否为None以打印错误文本。

在with语句中使用该上下文管理器。由于它返回一个列表对象,我们只需将返回值赋值给directory_list变量。在with语句的主体中,我们打印这个列表。运行程序后在输出中,可以看到项目目录中的内容列表。记住,"."表示当前目录,在我们的例子中是项目根目录(由于项目环境不同,输出内容可能也不一样)。

6. 函数形式上下文管理器

前文中,我们学习了如何使用类语法定义上下文管理器。但是有点繁琐和冗长。因为需要明确地实现__enter__和exit__方法,还需要处理可能的异常。所以希望Python中能有在创建上下文管理器更好的方法:基于函数的上下文管理器。

其实函数上下文管理器是使用生成器和contextlib.contextmanager装饰器的特殊函数。 contextlib.contextmanager装饰器负责实现上下文管理器协议。

下面就来定义一个函数型上下文管理器。

from contextlib import contextmanager

# 定义上下文管理器函数
@contextmanager
def function_based_context_manager():
print("进入上下文: __enter__")
yield "这是个基于上下文管理器的函数"
print("离开上下文: __exit__")

# with语句中使用上下文管理器函数
with function_based_context_manager() as yield_text:
print(yield_text)

运行程序输出结果类似如下:

进入上下文: __enter__
这是个基于上下文管理器的函数
离开上下文: __exit__

在上面代码中,我们定义了一个作为上下文管理器的自定义函数。contextmanager装饰器将常规函数转换为全堆栈上下文管理器(自动实现上下文管理器的协议)。如果你为函数提供了@contextmanager装饰器,就不需要担心实现__enter__和__exit__函数。

代码中的yield语句在基于类的上下文管理器中的__enter__方法中充当返回语句。由于我们使用了yield语句,故此,这个基于函数的上下文管理器也是生成器函数。

再来定义一个新的上下文管理器。这一次,它将以写的模式打开一个文件并添加一些文本。示例如下:

Python-Programmierung: Context Manager leicht verstehen (Context Manager)

代码清单

在清单中,我们定义了一个基于函数的上下文管理器。在try块中,它尝试打开指定路径中的文件,并指定了文件的默认编码集。如果它成功地打开它,那么它将生成(返回)file_object。在finally块中,我们检查是否有一个file_object要关闭。如果file_object不是None,则关闭file_object。

In der with-Anweisung rufen wir den Kontextmanager mit dem Dateinamen funBasedContextManagers.txt auf. Der Kontextmanager öffnet die Datei im Schreibmodus und gibt das Dateiobjekt zurück, das wir einfach Datei nennen. Schreiben Sie dann einen Text in diese Datei. Denken Sie daran, dass der Modus „w“ eine leere Datei erstellt, wenn eine solche Datei nicht vorhanden ist.

Führen Sie das obige Programm aus. Wenn die Datei nicht vorhanden ist, wird eine Datei mit dem entsprechenden Namen generiert und der geschriebene Inhalt bleibt erhalten. Wenn die Datei vorhanden ist, wird der Inhalt jedes Mal in die Quelldatei geschrieben. Bitte beachten Sie diesen Vorgang.

Um solche „Abschlussarbeiten“ zu erledigen, ist es besonders praktisch, einen Kontextmanager zu verwenden, insbesondere wenn es um Datenbankoperationen geht. Beispielsweise können Sie einen selbst umschließen, um die Verbindung automatisch zu schließen usw.

Zusammenfassung dieses Artikels

In dieser Ausgabe haben wir die Programmierinhalte im Zusammenhang mit Kontextmanagern vorgestellt, z. B. die Erstellung von Kontextmanagern, Kontextmanagerprotokollen, benutzerdefinierten Kontextmanagern in Klassenform und funktionalen Kontextmanagern usw. Die meisten relevanten Inhalte werden mit praktischem Code demonstriert und erklärt. Wenn Sie Ihre Programmierkenntnisse verbessern möchten, ist das Eingeben von Code mit Ihren Händen eine wesentliche Voraussetzung.

Das obige ist der detaillierte Inhalt vonPython-Programmierung: Context Manager leicht verstehen (Context Manager). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:51cto.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen