web-dev-qa-db-fra.com

Utilisation de python "avec" instruction avec le bloc try-except

Est-ce la bonne façon d'utiliser l'instruction python "avec" en combinaison avec un bloc try-except ?:

try:
    with open("file", "r") as f:
        line = f.readline()
except IOError:
    <whatever>

Si c'est le cas, alors, en considérant l'ancienne façon de faire les choses:

try:
    f = open("file", "r")
    line = f.readline()
except IOError:
    <whatever>
finally:
    f.close()

Le principal avantage de la déclaration "avec" est-il que nous pouvons nous débarrasser de trois lignes de code? Cela ne semble pas si convaincant pour moi pour ce cas d'utilisation (bien que je sache que l'instruction "with" a d'autres utilisations).

EDIT: La fonctionnalité des deux blocs de code ci-dessus est-elle identique?

EDIT2: Les premières réponses parlent généralement des avantages de l'utilisation de "avec", mais ceux-ci semblent présenter un avantage marginal. Nous avons tous (ou aurions dû) appeler explicitement f.close () depuis des années. Je suppose qu'un avantage est que les codeurs bâclés tireront profit de l'utilisation de "avec".

86
gaefan
  1. Les deux blocs de code que vous avez donnés sont non équivalents
  2. Le code que vous avez décrit comme étant l'ancienne manière de faire présente un bogue grave: en cas d'échec de l'ouverture du fichier, vous obtiendrez une seconde exception dans le fichier finally clause parce que f n'est pas lié.

Le code de style ancien équivalent serait:

try:
    f = open("file", "r")
    try:
        line = f.readline()
    finally:
        f.close()
except IOError:
    <whatever>

Comme vous pouvez le constater, l'instruction with peut rendre les choses moins sujettes aux erreurs. Dans les versions plus récentes de Python (2.7, 3.1), vous pouvez également combiner plusieurs expressions dans une instruction with. Par exemple:

with open("input", "r") as inp, open("output", "w") as out:
    out.write(inp.read())

En plus de cela, je considère personnellement comme une mauvaise habitude d’attraper toute exception le plus tôt possible. Ce n'est pas le but des exceptions. Si la fonction qui peut échouer IO) fait partie d'une opération plus complexe, dans la plupart des cas, l'erreur IOError doit abandonner l'ensemble de l'opération et être traitée à un niveau externe. Utiliser with déclarations, vous pouvez vous débarrasser de tous ces try...finally déclarations aux niveaux intérieurs.

126
Bernd Petersohn

Si le contenu du bloc finally est déterminé par les propriétés de l'objet fichier en cours d'ouverture, pourquoi l'implémenteur de l'objet fichier ne serait-il pas celui qui écrira le bloc finally? C'est l'avantage de l'instruction with, beaucoup plus que la sauvegarde de trois lignes de code dans ce cas particulier.

Et oui, la façon dont vous avez combiné with et try-except est à peu près la seule façon de le faire, car les erreurs exceptionnelles provoquées dans l'instruction open ne peuvent pas être capturées dans le bloc with.

6
Peter Milley

Je pense que vous vous êtes trompé en déclarant "avec" que cela ne fait que réduire les lignes. Il effectue en réalité l’initialisation et gère le démontage.

Dans votre cas "avec" fait

  • ouvrir un fichier,
  • traiter son contenu, et
  • assurez-vous de le fermer.

Voici un lien pour comprendre "avec" déclaration: http://effbot.org/zone/python-with-statement.htm

Edit: Oui, votre utilisation de "avec" est correcte et les fonctionnalités des deux blocs de code sont identiques. Question sur pourquoi utiliser "avec"? c'est à cause des avantages que vous obtenez avec. comme vous avez mentionné à propos de manquer accidentellement f.close ().

1
YoK