A quoi sert la déclaration python "with"?


Answers

Je suggérerais deux conférences intéressantes:

  • PEP 343 La déclaration "avec"
  • Effbot Comprendre l'instruction "with" de Python

1. L'instruction with est utilisée pour envelopper l'exécution d'un bloc avec des méthodes définies par un gestionnaire de contexte. Cela permet d' try...except...finally commun try...except...finally les modèles d'utilisation doivent être encapsulés pour une réutilisation pratique.

2. Vous pourriez faire quelque chose comme:

with open("foo.txt") as foo_file:
    data = foo_file.read()

OU

from contextlib import nested
with nested(A(), B(), C()) as (X, Y, Z):
   do_something()

OU (Python 3.1)

with open('data') as input_file, open('result', 'w') as output_file:
   for line in input_file:
     output_file.write(parse(line))

OU

lock = threading.Lock()
with lock:
    # Critical section of code

3. Je ne vois aucun Antipattern ici.
Citation de plongée en Python :

essayer .. finalement est bon. avec c'est mieux.

4. Je suppose que c'est lié à l'habitude des programmeurs d'utiliser try..catch..finally d'autres langues.

Question

Je suis tombé sur le Python with déclaration pour la première fois aujourd'hui. J'utilise Python à la légère depuis plusieurs mois et je ne savais même pas de son existence! Compte tenu de son statut quelque peu obscur, je pensais qu'il serait utile de demander:

  1. A quoi sert l'instruction Python with ?
  2. Qu'utilisez vous pour ça?
  3. Y a-t-il des pièges que je dois connaître, ou des anti-patterns communs associés à son utilisation? Tous les cas où il est préférable d' try..finally with ?
  4. Pourquoi n'est-il pas utilisé plus largement?
  5. Quelles sont les classes de bibliothèques standard compatibles?



Un exemple d'antipattern pourrait être d'utiliser le dans une boucle alors qu'il serait plus efficace d'avoir le with dehors de la boucle

par exemple

for row in lines:
    with open("outfile","a") as f:
        f.write(row)

contre

with open("outfile","a") as f:
    for row in lines:
        f.write(row)

La première façon est d'ouvrir et de fermer le fichier pour chaque row ce qui peut causer des problèmes de performance par rapport à la deuxième façon avec l'ouverture et la fermeture du fichier une seule fois.




Voir PEP 343 - L'instruction 'with' , il y a un exemple de section à la fin.

... nouvelle déclaration "avec" au langage Python pour permettre de factoriser les utilisations standard des instructions try / finally.




les points 1, 2 et 3 étant raisonnablement bien couverts:

4: c'est relativement nouveau, seulement disponible en python2.6 + (ou python2.5 en utilisant from __future__ import with_statement )




Un autre exemple de prise en charge prête à l'emploi, et peut-être un peu déroutant au premier abord lorsque vous êtes habitué au comportement interne d' open() , sont connection objets de connection de modules de base de données populaires tels que:

Les objets de connection sont des gestionnaires de contextes et, en tant que tels, peuvent être utilisés dès le début dans une with-statement , mais en utilisant la remarque ci-dessus, il faut:

Lorsque le with-block est terminé, avec ou sans exception, la connexion n'est pas fermée . Dans le cas où le with-block termine avec une exception, la transaction est annulée, sinon la transaction est validée.

Cela signifie que le programmeur doit prendre soin de fermer la connexion lui-même, mais permet d'acquérir une connexion, et l'utiliser dans plusieurs with-statements , comme indiqué dans les psycopg2 :

conn = psycopg2.connect(DSN)

with conn:
    with conn.cursor() as curs:
        curs.execute(SQL1)

with conn:
    with conn.cursor() as curs:
        curs.execute(SQL2)

conn.close()

Dans l'exemple ci-dessus, vous remarquerez que les objets cursor de psycopg2 sont également des gestionnaires de contextes. De la documentation pertinente sur le comportement:

Lorsqu'un cursor quitte le with-block il est fermé, libérant toute ressource éventuellement associée à celui-ci. L'état de la transaction n'est pas affecté.




Links