L'instruction with et le gestionnaire de contexte en Python

高洛峰
Libérer: 2017-03-01 14:15:40
original
1235 Les gens l'ont consulté

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)
Copier après la connexion

équivaut à la simplification de la situation suivante :

var = manager.__enter__()
try:
  do_something(var)
finally:
  manager.__exit__()
Copier après la connexion

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')
Copier après la connexion

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')
Copier après la connexion

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()
Copier après la connexion

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()
Copier après la connexion

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")
Copier après la connexion

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()
Copier après la connexion


Sortie :

enter
hello world
exit
Copier après la connexion

La fonction __exit__ complète est la suivante :

def __exit__(self,exc_type,exc_value,exc_tb)
Copier après la connexion

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
Copier après la connexion


Le. le résultat est :

  enter
  ok
  exit
Copier après la connexion

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
Copier après la connexion

4. >Pour :

with open(filename,mode) as reader:
  with open(filename1,mode1) as writer:
    writer.write(reader.read())
Copier après la connexion

peut être simplifié par contextlib.nested :

with contextlib.nested(open(filename,mode),open(filename1,mode1)) as (reader,writer):
  writer.write(reader.read())
Copier après la connexion

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())
Copier après la connexion

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'
Copier après la connexion

Sortie :



__init__
ok
close()
Copier après la connexion


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

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!