Maison  >  Article  >  développement back-end  >  L'instruction with et le gestionnaire de contexte en Python

L'instruction with et le gestionnaire de contexte en Python

高洛峰
高洛峰original
2017-03-01 14:15:401232parcourir

En tant qu'objet gestionnaire de contexte en Python, vous pouvez utiliser l'instruction with. L'utilisation du module contextlib qui fournit le gestionnaire de contexte est une compétence avancée dans la programmation Python. Examinons de plus près l'instruction with et la gestion du contexte dans. Python. Résumé de l'apprentissage automatique :

0. À propos du gestionnaire de contexte
Le gestionnaire de contexte est un objet qui peut être utilisé dans l'instruction with et possède les méthodes __enter__ et __exit__.

with manager as var:
  do_something(var)

équivaut à la simplification de la situation suivante :

var = manager.__enter__()
try:
  do_something(var)
finally:
  manager.__exit__()

En d'autres termes, le protocole de gestion de contexte défini dans PEP 343 permet à la structure ennuyeuse try...sauf...finally d'être abstraite dans une classe distincte, ne laissant que la partie do_something préoccupante.

La méthode __enter__ est appelée en premier. Il peut renvoyer la valeur attribuée à var. La partie as est facultative : si elle n'apparaît pas, la valeur de retour de enter est simplement ignorée.
Le code sous l'instruction with est exécuté. Comme les clauses try, soit elles s'exécutent avec succès, s'interrompent, continuent ou reviennent, soit elles peuvent lever une exception. Dans les deux cas, une fois le bloc terminé, la méthode __exit__ est appelée. Si une exception est levée, les informations sur l'exception sont transmises à __exit__, qui est abordé dans la section suivante. Normalement, les exceptions peuvent être ignorées, comme dans une clause final, et seront renvoyées après la fin de __exit__.
Supposons que nous voulions nous assurer qu'un fichier est fermé immédiatement après avoir terminé l'opération d'écriture :

>>> class closing(object):
...  def __init__(self, obj):
...   self.obj = obj
...  def __enter__(self):
...   return self.obj
...  def __exit__(self, *args):
...   self.obj.close()
>>> with closing(open('/tmp/file', 'w')) as f:
...  f.write('the contents\n')

Ici, nous nous assurons que le bloc with est appelé quand il quitte f.close(). La fermeture d'un fichier étant une opération très courante, ce support est déjà présent dans la classe file. Il possède une méthode __exit__ qui appelle close et agit lui-même comme un gestionnaire de contexte.

>>> with open('/tmp/file', 'a') as f:
...  f.write('more contents\n')

essayez... enfin, l'usage courant est de libérer des ressources. Les différentes situations sont implémentées de la même manière : la ressource est acquise lors de la phase __enter__, libérée lors de la phase __exit__, et une exception est également passée si elle est levée. Tout comme les opérations sur les fichiers, il s'agit souvent d'une opération naturelle après l'utilisation de l'objet, et la prise en charge intégrée la rend pratique. Avec chaque version, Python est pris en charge à plusieurs endroits.

1. Comment utiliser le gestionnaire de contexte :

Comment ouvrir un fichier et écrire "hello world"

filename="my.txt"
mode="w"
writer=open(filename,mode)
writer.write("hello world")
writer.close()

Lorsqu'une exception se produit (par exemple, le disque est plein), il n'y a aucune chance d'exécuter la ligne 5. Bien sûr, nous pouvons utiliser des blocs d'instructions try-finally pour l'empaquetage :

writer=open(filename,mode)
try:
  writer.write("hello world")
finally:
  writer.close()

Lorsque nous effectuons des opérations complexes, l'instruction try-finally deviendra moche, réécrivez en utilisant l'instruction with :

with open(filename,mode) as writer:
  writer.write("hello world")

as fait référence au contenu renvoyé par la fonction open() et l'attribue à la nouvelle valeur . avec termine la tâche d'essai-finalement.

2. Gestionnaire de contexte personnalisé

L'instruction with est similaire à try-finally, fournissant un mécanisme de contexte. Pour appliquer l'instruction with, la classe doit fournir deux fonctions intégrées __enter__ et __exit__. Le premier est exécuté avant l’exécution du code principal et le second est exécuté après l’exécution du code principal. Les variables après as sont renvoyées dans la fonction __enter__.

class echo():
  def output(self):
    print "hello world"
  def __enter__(self):
    print "enter"
    return self #可以返回任何希望返回的东西
  def __exit__(self,exception_type,value,trackback):
    print "exit"
    if exception_type==ValueError:
      return True
    else:
      return Flase
 
>>>with echo as e:
  e.output()


Sortie :

enter
hello world
exit

La fonction __exit__ complète est la suivante :

def __exit__(self,exc_type,exc_value,exc_tb)

Parmi eux, exc_type : type d'exception ; exc_value : valeur d'exception ; exc_tb : informations de suivi des exceptions

Lorsque __exit__ renvoie True, l'exception n'est pas propagée

3. module contextlib

Le rôle du module contextlib est de fournir un module plus facile à utiliser. gestionnaire de contexte, qui est implémenté via Generator. Le contextmanager de contextlib sert de décorateur pour fournir un mécanisme de gestion de contexte au niveau de la fonction. Les frameworks couramment utilisés sont les suivants :

from contextlib import contextmanager
@contextmanager
def make_context():
  print 'enter'
  try:
    yield "ok"
  except RuntimeError,err:
    print 'error',err
  finally:
    print 'exit'
    
>>>with make_context() as value:
  print value


Le. le résultat est :

  enter
  ok
  exit

Parmi eux, le rendement est écrit en try-finally pour garantir la sécurité des exceptions (peut gérer les exceptions). la variable après as est renvoyée par rendement. L'instruction avant rendement peut être considérée comme l'opération avant l'exécution du bloc de code, et l'opération après rendement peut être considérée comme l'opération dans la fonction __exit__.

Prenons le verrouillage des threads comme exemple :

@contextlib.contextmanager
def loudLock():
  print 'Locking'
  lock.acquire()
  yield
  print 'Releasing'
  lock.release()
 
with loudLock():
  print 'Lock is locked: %s' % lock.locked()
  print 'Doing something that needs locking'
 
#Output:
#Locking
#Lock is locked: True
#Doing something that needs locking
#Releasing

4. >Pour :

with open(filename,mode) as reader:
  with open(filename1,mode1) as writer:
    writer.write(reader.read())

peut être simplifié par contextlib.nested :

with contextlib.nested(open(filename,mode),open(filename1,mode1)) as (reader,writer):
  writer.write(reader.read())

est remplacé par une nouvelle syntaxe dans Python 2.7 et versions ultérieures :

with open(filename,mode) as reader,open(filename1,mode1) as writer:
  writer.write(reader.read())

5. 🎜>

La classe file prend directement en charge l'API du gestionnaire de contexte, mais certains objets représentant des handles ouverts ne sont pas pris en charge, comme les objets renvoyés par urllib.urlopen(). Certaines classes héritées utilisent également la méthode close() mais ne prennent pas en charge l'API du gestionnaire de contexte. Pour vous assurer que le handle est fermé, vous devez créer un gestionnaire de contexte pour celui-ci à l'aide de Closure() (appelant la méthode close de la classe).

import contextlib
class myclass():
  def __init__(self):
    print '__init__'
  def close(self):
    print 'close()'
   
with contextlib.closing(myclass()):
  print 'ok'

Sortie :



__init__
ok
close()


Pour plus d'articles liés à l'instruction with et au gestionnaire de contexte en Python, veuillez faire attention au site Web PHP chinois !

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn