Le contenu de cet article concerne l'utilisation de with en python. Les amis dans le besoin peuvent s'y référer
Certaines tâches peuvent devoir être configurées à l'avance et nettoyées par la suite. Pour ce scénario, l'instruction with de Python fournit un moyen très pratique de le gérer. Un bon exemple est la gestion de fichiers, où vous devez obtenir un descripteur de fichier, lire les données du fichier, puis fermer le descripteur de fichier.
Si vous n'utilisez pas l'instruction with, le code est le suivant :
file = open("/tmp/foo.txt") data = file.read()file.close()
Il y a deux problèmes ici :
Le premier est que vous pouvez oublier de fermer le descripteur de fichier ;
L'autre est la lecture du fichier. Une exception s'est produite lors de la récupération des données et aucun traitement n'a été effectué.
Voici une version améliorée qui gère les exceptions :
try: f = open('xxx')except: print 'fail to open' exit(-1)try: do somethingexcept: do somethingfinally: f.close()
Bien que ce code fonctionne bien, il est trop verbeux.
C'est le moment pour With de montrer ses compétences. En plus d'avoir une syntaxe plus élégante, with peut également très bien gérer les exceptions générées par le contexte.
Ce qui suit est le code de la version with :
with open("/tmp/foo.txt") as file: data = file.read()
Après l'évaluation de l'instruction qui suit with, la __enter__ de ? l'objet est renvoyé. La méthode () est appelée et la valeur de retour de cette méthode sera attribuée à la variable après as.
Lorsque tous les blocs de code suivant avec sont exécutés, la méthode __exit__() de l'objet précédemment renvoyé sera appelée.
L'exemple suivant peut illustrer spécifiquement comment fonctionne :
#!/usr/bin/env python# with_example01.pyclass Sample: def __enter__(self): print "In __enter__()" return "Foo" def __exit__(self, type, value, trace): print "In __exit__()"def get_sample(): return Sample()with get_sample() as sample: print "sample:", sample
Exécutez le code, le résultat est le suivant
bash-3.2$ ./with_example01.pyIn __enter__()sample: FooIn __exit__()
正如你看到的: 1. __enter__()方法被执行 2. __enter__()方法返回的值 - 这个例子中是”Foo”,赋值给变量’sample’ 3. 执行代码块,打印变量”sample”的值为 “Foo” 4. __exit__()方法被调用
with真正强大之处是它可以处理异常。可能你已经注意到Sample类的 __exit__ 方法有三个参数 val, type 和 trace。 这些参数在异常处理中相当有用。我们来改一下代码,看看具体如何工作的。
#!/usr/bin/env python# with_example02.pyclass Sample: def __enter__(self): return self def __exit__(self, type, value, trace): print "type:", type print "value:", value print "trace:", trace def do_something(self): bar = 1/0 return bar + 10with Sample() as sample: sample.do_something()
这个例子中,with后面的get_sample()变成了Sample()。这没有任何关系,只要紧跟with后面的语句所返回的对象有 __enter__() 和 __exit__() 方法即可。此例中,Sample()的 __enter__() 方法返回新创建的Sample对象,并赋值给变量sample。
代码执行后:
bash-3.2$ ./with_example02.py type: <type 'exceptions.ZeropisionError'>value: integer pision or modulo by zerotrace: <traceback object at 0x1004a8128> Traceback (most recent call last): File "./with_example02.py", line 19, in <module> sample.do_something() File "./with_example02.py", line 15, in do_something bar = 1/0ZeropisionError: integer pision or modulo by zero
实际上,在with后面的代码块抛出任何异常时,__exit__() 方法被执行。正如例子所示,异常抛出时,与之关联的type,value和stack trace传给 __exit__() 方法,因此抛出的ZeropisionError异常被打印出来了。开发库时,清理资源,关闭文件等等操作,都可以放在 __exit__ 方法当中。
另外,__exit__ 除了用于tear things down,还可以进行异常的监控和处理,注意后几个参数。要跳过一个异常,只需要返回该函数True即可。
下面的样例代码跳过了所有的TypeError,而让其他异常正常抛出。
def __exit__(self, type, value, traceback): return isinstance(value, TypeError)
上文说了 __exit__ 函数可以进行部分异常的处理,如果我们不在这个函数中处理异常,他会正常抛出,这时候我们可以这样写(python 2.7及以上版本,之前的版本参考使用contextlib.nested这个库函数):
try: with open( "a.txt" ) as f : do something except xxxError: do something about exception
总之,with-as表达式极大的简化了每次写finally的工作,这对保持代码的优雅性是有极大帮助的。
如果有多个项,我们可以这么写:
with open("x.txt") as f1, open('xxx.txt') as f2: do something with f1,f2
因此,Python的with语句是提供一个有效的机制,让代码更简练,同时在异常产生时,清理工作更简单。
Pour utiliser l'instruction with, vous devez d'abord comprendre le concept de gestionnaire de contexte. Avec un gestionnaire de contexte, l'instruction with peut fonctionner.
Ce qui suit est un ensemble de concepts liés aux gestionnaires de contexte et aux déclarations.
Protocole de gestion de contexte : contient les méthodes __enter__() et __exit__(). Les objets qui prennent en charge ce protocole doivent implémenter ces deux méthodes.
Context Manager : Un objet qui prend en charge le protocole de gestion de contexte. Cet objet implémente les méthodes __enter__() et __exit__(). Le gestionnaire de contexte définit le contexte d'exécution à établir lors de l'exécution de l'instruction with et est responsable de l'exécution des opérations d'entrée et de sortie dans le contexte du bloc d'instruction with. Un gestionnaire de contexte est généralement appelé à l'aide de l'instruction with, mais peut également être utilisé en appelant directement ses méthodes.
Contexte d'exécution : créé par le gestionnaire de contexte et implémenté via les méthodes __enter__() et __exit__() du gestionnaire de contexte. La méthode __enter__() entre dans le contexte d'exécution avant que le corps de l'instruction ne soit exécuté. contexte d'exécution après l'exécution du corps de l'instruction. L'instruction with prend en charge le concept de contexte d'exécution.
Expression contextuelle : expression qui suit le mot-clé with dans l'instruction with, qui renvoie un objet gestionnaire de contexte.
Corps de l'instruction (with-body) : le bloc de code enveloppé dans l'instruction with appellera la méthode __enter__() du gestionnaire de contexte avant d'exécuter le corps de l'instruction, et la méthode __exit__() sera exécutée une fois le corps de l'instruction terminé. exécuté.
Liens connexes :
1.http://blog.kissdata.com/2014/05/23/python-with.html
2.https://www.ibm .com/developerworks/cn/opensource/os-cn-pythonwith/
Recommandations associées :
Comment comprendre l'instruction with en Python
Explication détaillée de l'utilisation de focus-within
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!