2010-09-04 14 views
74

Est-ce la bonne façon d'utiliser le python « avec » déclaration en combinaison avec un try-except bloc ?:En utilisant python « avec » déclaration avec try-except

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

Si elle est, puis envisage l'ancienne façon de faire les choses:

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

est le principal avantage de la déclaration « avec » ici que nous pouvons nous débarrasser de trois lignes de code? Cela ne me semble pas très convaincant pour ce cas d'utilisation (bien que je comprenne 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 celles-ci semblent présenter un avantage marginal ici. Nous avons tous (ou aurions dû) appeler explicitement f.close() depuis des années. Je suppose que l'un des avantages est que les codeurs bâclés bénéficieront d'utiliser "avec".

+0

double possible de [Attraper une exception en utilisant un Python 'avec' déclaration] (http://stackoverflow.com/questions/713794/catching -an-exception-while-using-a-python-with-statement) –

Répondre

112
  1. Les deux blocs de code vous a donné sont pas équivalent
  2. Le code décrit comme ancienne de faire les choses a un bug grave: en cas d'ouvrir le fichier échoue obtiendrai une deuxième exception dans la clause finally car f n'est pas liée.

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 voir, la déclaration with peut rendre les choses moins sujette aux erreurs. Dans les nouvelles versions 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 outre, je considère personnellement comme une mauvaise habitude d'attraper une exception le plus tôt possible. Ce n'est pas le but des exceptions. Si la fonction E/S qui peut échouer fait partie d'une opération plus compliquée, dans la plupart des cas, IOError doit interrompre toute l'opération et donc être traitée au niveau externe. En utilisant les instructions with, vous pouvez vous débarrasser de toutes ces instructions try...finally aux niveaux internes.

6

Si le contenu du bloc finally est déterminé par les propriétés de l'objet fichier ouvert, pourquoi l'implémenteur de l'objet fichier ne devrait-il pas écrire le bloc finally? C'est l'avantage de l'instruction with, bien plus que de vous sauver trois lignes de code dans cette instance particulière.

Et oui, la façon dont nous avons combiné with et try-except est à peu près la seule façon de le faire, comme des erreurs exceptionnelles causées dans la déclaration open elle-même ne peut pas être pris dans le bloc with.

1

Je pense que vous vous êtes trompé à propos de "avec" une déclaration qui ne fait que réduire les lignes. Il effectue réellement l'initialisation et gère le démontage.

Dans votre cas "avec" fait

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

Voici le lien pour la compréhension « avec » déclaration: http://effbot.org/zone/python-with-statement.htm

Edit: Oui votre utilisation de « avec » est correcte et la fonctionnalité des deux des blocs de code est identique. Question sur les raisons d'utiliser "with"? C'est à cause des avantages que vous obtenez avec. comme vous l'avez mentionné à propos de f.close() accidentellement manquant.

-3

La façon plus Pythonic les codes suivants est:

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

try: 
    f = open("file", "r") 
except IOError: 
    <whatever> 
else: 
    f.close() 
+0

J'ai ajouté le formatage de code pour vous; ça le rend plus facile à lire. Mais vous voudrez peut-être vérifier pour vous assurer que je n'ai pas brisé l'indentation. – andrewsi

+0

Non, votre version ne fait pas la même chose que le code original. Même si vous ajoutez l'appel 'readline()' manquant, votre version ne ferme pas le fichier si 'readline()' donne un 'IOError'. –