Maison >développement back-end >Tutoriel Python >Programmation Python : comprendre facilement Context Manager (Context Manager)

Programmation Python : comprendre facilement Context Manager (Context Manager)

PHPz
PHPzavant
2023-04-12 14:07:132340parcourir

Avant-propos

Cet article se concentre sur l'explication et l'application de la gestion du contexte Python. Ou par des exemples de code, une compréhension comparative et un apprentissage, afin de parvenir à la compréhension, à la maîtrise et à l'application de « plus de vitesse, une meilleure économie ». Sans plus tarder, commençons -

1. Qu'est-ce qu'un gestionnaire de contexte ? Un gestionnaire de contexte est un objet qui définit le contexte d'exécution à établir lors de l'exécution d'une instruction with. Un gestionnaire de contexte est un environnement d'exécution qui gère automatiquement l'entrée et la sortie du contexte dans lequel un bloc de code s'exécute. Les gestionnaires de contexte sont généralement appelés à l'aide d'une instruction with, mais peuvent également être utilisés en appelant directement leurs méthodes.

Les utilisations typiques des gestionnaires de contexte incluent l'enregistrement et la restauration de divers états globaux, le verrouillage et le déverrouillage de ressources, la fermeture de fichiers ouverts, etc.

Dans ce chapitre, nous apprendrons comment utiliser les gestionnaires de contexte en Python et comment personnaliser les gestionnaires de contexte.

1.With Instruction

with L'instruction est utilisée pour l'exécution des blocs de wrapper de méthode définis par le gestionnaire de contexte. Cela permet d'encapsuler le modèle d'utilisation commun try...sauf...finally pour une réutilisation facile. L'instruction with fournit un code plus court et réutilisable par rapport au bloc traditionnel try...sauf...finally.

Dans la bibliothèque standard Python, de nombreuses classes prennent en charge l'instruction with. Un exemple très courant est la fonction intégrée open(), qui fournit un modèle pour traiter les objets fichier à l'aide de l'instruction with.

Ce qui suit est la syntaxe générale de l'instruction with :

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

Regardons un exemple d'utilisation de la fonction open(). Il y a un fichier texte dans le dossier des fichiers du projet en cours. Le nom du fichier est color_names.txt, qui contient des noms de couleurs (vous pouvez fournir vous-même du contenu textuel). Nous voulons ouvrir et imprimer le contenu de ce fichier en utilisant la fonction open() et l'instruction with. L'exemple de code est le suivant :

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())

Le résultat de l'exécution du programme est le suivant

red
orange
yellow
green
blue
white
black

Dans la liste ci-dessus, ce que vous voyez est un cas d'utilisation courant de l'instruction with. Nous utilisons la fonction open() pour ouvrir le fichier sur le chemin (chemin) donné, et la fonction open() renvoie l'objet fichier en mode lecture seule. Le code utilise ensuite cet objet fichier pour lire et imprimer son contenu via le code : print(file.read()).

L'exemple ci-dessus est une utilisation typique du gestionnaire de contexte. Afin de mieux comprendre et appliquer les gestionnaires de contexte, nous devons continuer à lire.

3. Context Manager Protocol

Context Manager Protocol, pour parler franchement, est le mécanisme de traitement du gestionnaire de contexte, ou la norme de protocole prédéterminée. Cette partie peut également être trouvée ici : Python Core Protocol. Par souci d’indépendance dans la lecture, reparlons-en ici.

L'instruction with de Python prend en charge le concept de contexte d'exécution défini par un gestionnaire de contexte. Ceci est accompli grâce à une paire de méthodes qui permettent à une classe définie par l'utilisateur de définir un contexte d'exécution qui est entré avant l'exécution du corps de l'instruction et qui est quitté à la fin de l'instruction.

Les méthodes mentionnées précédemment sont appelées protocoles de gestion de contexte. Examinons ces deux méthodes en détail :

1) __enter__(self)

Cette méthode est appelée par l'instruction with pour entrer dans le contexte d'exécution lié à l'objet actuel. L'instruction with lie la valeur de retour de cette méthode à la cible (le cas échéant) spécifiée dans la clause as de l'instruction.

Le gestionnaire de contexte renvoyé dans l'exemple ci-dessus est l'objet fichier. En arrière-plan, l'objet fichier se renvoie lui-même depuis __enter__() pour permettre à open() d'être utilisé comme expression contextuelle dans une instruction with.

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

Cette méthode est appelée lorsque l'exécution quitte le bloc de code with. Il quitte le contexte d'exécution associé à cet objet. Les paramètres décrivent les informations d'exception qui ont provoqué la fermeture du contexte. Si le contexte est quitté sans exception, les trois paramètres seront Aucun.

Si une exception est fournie et que vous souhaitez que la méthode supprime l'exception (c'est-à-dire l'empêche de se propager), elle doit alors renvoyer une valeur True. Sinon, l'exception sera gérée normalement à la sortie de cette méthode. La méthode __exit__() renvoie une valeur booléenne, qui peut être True ou False.

Le processus d'exécution d'une instruction with à l'aide des méthodes du protocole du gestionnaire de contexte est le suivant :

with EXPRESSION as TARGET:
SUITE

Évaluez l'expression de contexte (EXPRESSION) pour obtenir le gestionnaire de contexte.
  • Chargez le __enter__() du gestionnaire de contexte pour une utilisation ultérieure.
  • Chargez le __exit__() du gestionnaire de contexte pour une utilisation ultérieure.
  • Appelez la méthode __enter__() du gestionnaire de contexte.
  • Si un TARGET est inclus dans l'instruction with, la valeur de retour de __enter__() lui sera attribuée.
  • Suite d'exécution (bloc de code dans le cadre de l'instruction with).
  • Appelez la méthode __exit__() du gestionnaire de contexte. Si l'exception a provoqué la fermeture de la suite, son type, sa valeur et son traçage sont transmis comme arguments à __exit__(). Sinon, trois paramètres Aucun seront fournis.
  • Si la suite se termine pour une raison autre qu'une exception, la valeur de retour de __exit__() est ignorée et l'exécution du code suivant (le cas échéant) continue à l'emplacement normal pour le type de sortie en cours d'exécution.

4. Gestionnaire de contexte de formulaire de classe

Maintenant que nous comprenons l'idée de base derrière le protocole du gestionnaire de contexte, implémentons-le dans une classe. Cette classe sera notre gestionnaire de contexte et nous l'utiliserons plus tard dans l'instruction with.

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

# 自定义上下文管理器类
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语句,故此,这个基于函数的上下文管理器也是生成器函数。

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

Programmation Python : comprendre facilement Context Manager (Context Manager)

代码清单

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

Dans l'instruction with, nous appelons le gestionnaire de contexte avec le nom de fichier funBasedContextManagers.txt. Le gestionnaire de contexte ouvre le fichier en mode écriture et renvoie l'objet fichier, que nous nommons simplement fichier. Ensuite, écrivez du texte dans ce fichier. N'oubliez pas que le mode 'w' créera un fichier vide si un tel fichier n'existe pas.

Exécutez le programme ci-dessus. Si le fichier n'existe pas, un fichier avec le nom correspondant sera généré et le contenu écrit sera conservé. Si le fichier existe, le contenu est écrit dans le fichier source à chaque fois. Veuillez faire attention à cette opération.

Pour gérer un travail de "finition" comme celui-ci, il est particulièrement pratique d'utiliser un gestionnaire de contexte, notamment lorsqu'il s'agit d'opérations de base de données. Par exemple, vous pouvez en envelopper un vous-même pour fermer automatiquement la connexion, etc.

Résumé de cet article

Dans ce numéro, nous avons présenté le contenu de programmation lié aux gestionnaires de contexte, comme la façon de créer des gestionnaires de contexte, des protocoles de gestionnaire de contexte, des gestionnaires de contexte de formulaire de classe personnalisés et des gestionnaires de contexte fonctionnels, etc. La plupart du contenu pertinent est démontré et expliqué avec un code pratique. Si vous souhaitez améliorer vos compétences en programmation, taper du code avec vos mains est une condition essentielle.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer