J'ai rencontré la with
déclaration Python pour la première fois aujourd'hui. J'utilise Python à la légère depuis plusieurs mois et je ne connaissais même pas son existence! Compte tenu de son statut quelque peu obscur, j'ai pensé qu'il valait la peine de demander:
- À quoi sert l'
with
instruction Python ? - Qu'utilisez vous pour ça?
- Y a-t-il des problèmes que je dois connaître ou des anti-schémas communs associés à son utilisation? Des cas où il vaut mieux l'utiliser
try..finally
quewith
? - Pourquoi n'est-il pas utilisé plus largement?
- Quelles classes de bibliothèque standard sont compatibles avec elle?
with
dans la documentation Python 3.Réponses:
Je pense que cela a déjà été répondu par d'autres utilisateurs avant moi, donc je ne l'ajoute que par souci d'exhaustivité: l'
with
instruction simplifie la gestion des exceptions en encapsulant les tâches de préparation et de nettoyage courantes dans les soi-disant gestionnaires de contexte . Plus de détails peuvent être trouvés dans PEP 343 . Par exemple, l'open
instruction est un gestionnaire de contexte en soi, qui vous permet d'ouvrir un fichier, de le garder ouvert tant que l'exécution se trouve dans le contexte de l'with
instruction où vous l'avez utilisée et de la fermer dès que vous quittez le contexte, que vous l'ayez quitté en raison d'une exception ou lors d'un flux de contrôle régulier. L'with
instruction peut donc être utilisée de manière similaire au modèle RAII en C ++: une ressource est acquise par lewith
et libérée lorsque vous quittez lewith
contexte.Voici quelques exemples: ouverture de fichiers avec
with open(filename) as fp:
, acquisition de verrous avecwith lock:
(oùlock
est une instance dethreading.Lock
). Vous pouvez également créer vos propres gestionnaires de contexte à l'aide ducontextmanager
décorateur decontextlib
. Par exemple, je l'utilise souvent lorsque je dois changer temporairement le répertoire en cours, puis revenir là où j'étais:Voici un autre exemple qui redirige temporairement
sys.stdin
,sys.stdout
etsys.stderr
à une autre poignée de fichiers et restaure eux plus tard:Et enfin, un autre exemple qui crée un dossier temporaire et le nettoie en quittant le contexte:
la source
with
instruction est conçue pour remplir une variable avec des données jusqu'à ce que les instructions en dessous soient complètes, puis libérer la variable?with open('myScript.py', 'r') as f: pass
. Je pensais pouvoir appeler la variablef
pour voir le contenu du texte du document, car c'est ce qui apparaît si le document a été attribué àf
par une régulièreopen
déclaration:f = open('myScript.py').read()
. Mais au lieu que je suis arrivé ce qui suit:<_io.TextIOWrapper name='myScript.py' mode='r' encoding='cp1252'>
. Qu'est-ce que ça veut dire?with
ne supprime pas la nécessitéread
du fichier réel. Leswith
appelsopen
- il ne sait pas ce que vous devez en faire - vous voudrez peut-être faire une recherche par exemple.with
instruction peut remplir une variable avec des données ou apporter d'autres modifications à l'environnement jusqu'à ce que les instructions en dessous soient terminées, puis effectue tout type de nettoyage nécessaire. Les types de nettoyage qui peuvent être effectués sont des choses comme la fermeture d'un fichier ouvert, ou comme @Tamas dans cet exemple, le retour des répertoires à l'endroit où vous étiez auparavant, etc. Puisque Python a un ramasse-miettes, la libération d'une variable n'est pas importante cas d'utilisation.with
est généralement utilisé pour d'autres types de nettoyage.Je suggérerais deux conférences intéressantes:
1. L'
with
instruction est utilisée pour encapsuler l'exécution d'un bloc avec des méthodes définies par un gestionnaire de contexte. Cela permettry...except...finally
d'encapsuler des modèles d'utilisation courants pour une réutilisation pratique.2. Vous pourriez faire quelque chose comme:
OU
OU (Python 3.1)
OU
3. Je ne vois aucun Antipattern ici.
Citant la plongée en Python :
4. Je suppose que c'est lié à l'habitude des programmeurs d'utiliser des
try..catch..finally
instructions provenant d'autres langues.la source
with
.L'
with
instruction Python est un support de langage intégré de l'Resource Acquisition Is Initialization
idiome couramment utilisé en C ++. Il est destiné à permettre l'acquisition et la libération en toute sécurité des ressources du système d'exploitation.L'
with
instruction crée des ressources dans une étendue / un bloc. Vous écrivez votre code en utilisant les ressources du bloc. Lorsque le bloc se ferme, les ressources sont libérées proprement, quel que soit le résultat du code dans le bloc (c'est-à-dire si le bloc se termine normalement ou en raison d'une exception).De nombreuses ressources de la bibliothèque Python qui obéissent au protocole requis par l'
with
instruction et peuvent donc être utilisées avec elle hors de la boîte. Cependant, n'importe qui peut créer des ressources qui peuvent être utilisées dans une instruction with en implémentant le protocole bien documenté: PEP 0343Utilisez-le chaque fois que vous acquérez des ressources dans votre application qui doivent être explicitement abandonnées, telles que des fichiers, des connexions réseau, des verrous, etc.
la source
Encore une fois pour être complet, j'ajouterai mon cas d'utilisation le plus utile pour les
with
déclarations.Je fais beaucoup de calcul scientifique et pour certaines activités, j'ai besoin de la
Decimal
bibliothèque pour des calculs de précision arbitraires. Certaines parties de mon code ont besoin d'une grande précision et pour la plupart des autres parties, j'ai besoin de moins de précision.J'ai défini ma précision par défaut sur un nombre faible, puis j'utilise
with
pour obtenir une réponse plus précise pour certaines sections:J'utilise beaucoup cela avec le test hypergéométrique qui nécessite la division de grands nombres résultant des factorielles de forme. Lorsque vous effectuez des calculs à l'échelle génomique, vous devez faire attention aux erreurs d'arrondi et de débordement.
la source
Un exemple d'antipattern pourrait être d'utiliser l'
with
intérieur d'une boucle alors qu'il serait plus efficace d'avoir l'with
extérieur de la bouclepar exemple
contre
La première méthode consiste à ouvrir et à fermer le fichier pour chacun,
row
ce qui peut entraîner des problèmes de performances par rapport à la seconde méthode avec ouvre et ferme le fichier une seule fois.la source
Voir PEP 343 - L'instruction 'with' , il y a un exemple de section à la fin.
la source
les points 1, 2 et 3 étant raisonnablement bien couverts:
4: il est relativement nouveau, uniquement disponible en python2.6 + (ou python2.5 en utilisant
from __future__ import with_statement
)la source
L'instruction with fonctionne avec les soi-disant gestionnaires de contexte:
http://docs.python.org/release/2.5.2/lib/typecontextmanager.html
L'idée est de simplifier la gestion des exceptions en effectuant le nettoyage nécessaire après avoir quitté le bloc 'with'. Certains des composants intégrés de python fonctionnent déjà en tant que gestionnaires de contexte.
la source
Un autre exemple de prise en charge prête à l'emploi, et qui peut être un peu déroutant au début lorsque vous êtes habitué au
open()
comportement intégré , sont lesconnection
objets de modules de base de données populaires tels que:Les
connection
objets sont des gestionnaires de contexte et en tant que tels peuvent être utilisés prêtswith-statement
à l'emploi dans un , cependant lors de l'utilisation de la remarque ci-dessus:Cela signifie que le programmeur doit prendre soin de fermer la connexion lui-même, mais permet d'acquérir une connexion et de l'utiliser en plusieurs
with-statements
, comme indiqué dans les documents psycopg2 :Dans l'exemple ci-dessus, vous remarquerez que les
cursor
objets depsycopg2
sont également des gestionnaires de contexte. De la documentation pertinente sur le comportement:la source
En python, l' instruction « with » est généralement utilisée pour ouvrir un fichier, traiter les données présentes dans le fichier et également pour fermer le fichier sans appeler une méthode close (). L'instruction «with» simplifie la gestion des exceptions en fournissant des activités de nettoyage.
Forme générale de avec:
note: pas besoin de fermer le fichier en appelant close () sur file-var.close ()
la source