Utilizzo dell'istruzione "with" di python con il blocco try-tranne


96

È questo il modo giusto per usare l'istruzione python "with" in combinazione con un blocco try-tranne ?:

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

Se lo è, quindi considerando il vecchio modo di fare le cose:

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

Il vantaggio principale dell'istruzione "with" qui è che possiamo sbarazzarci di tre righe di codice? Non mi sembra così convincente per questo caso d'uso (anche se capisco che l'istruzione "with" ha altri usi).

EDIT: la funzionalità dei due blocchi di codice precedenti è identica?

EDIT2: Le prime risposte parlano generalmente dei vantaggi dell'utilizzo di "con", ma qui sembrano di beneficio marginale. Abbiamo chiamato tutti (o avremmo dovuto) esplicitamente f.close () per anni. Suppongo che un vantaggio sia che i programmatori sciatti trarranno vantaggio dall'utilizzo di "con".



Per me, non doversi ricordare di chiudere le cose () in un'istruzione finalmente è una ragione sufficiente per usare 'con'. Ho visto un sacco di codice non riuscire a chiudere le sue risorse. E "con" non ha svantaggi per quanto posso vedere.
Raúl Salinas-Monteagudo

Risposte:


139
  1. I due blocchi di codice che hai fornito non sono equivalenti
  2. Il codice che hai descritto come un vecchio modo di fare le cose ha un grave bug: nel caso in cui l'apertura del file fallisca otterrai una seconda eccezione nella finallyclausola perché fnon è vincolata.

Il codice vecchio stile equivalente sarebbe:

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

Come puoi vedere, l' withaffermazione può rendere le cose meno soggette a errori. Nelle versioni più recenti di Python (2.7, 3.1), puoi anche combinare più espressioni in un'unica withistruzione. Per esempio:

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

Oltre a ciò, personalmente considero una cattiva abitudine cogliere un'eccezione il prima possibile. Questo non è lo scopo delle eccezioni. Se la funzione IO che può fallire fa parte di un'operazione più complicata, nella maggior parte dei casi IOError dovrebbe interrompere l'intera operazione e quindi essere gestito a un livello esterno. Usando le withaffermazioni, puoi sbarazzarti di tutte queste try...finallyaffermazioni a livelli interiori.


7

Se il contenuto del finallyblocco è determinato dalle proprietà dell'oggetto file che viene aperto, perché l'implementatore dell'oggetto file non dovrebbe essere quello che scrive il finallyblocco? Questo è il vantaggio withdell'istruzione, molto più che salvare tre righe di codice in questa particolare istanza.

E sì, il modo in cui hai combinato withed try-exceptè praticamente l'unico modo per farlo, poiché errori eccezionali causati all'interno opendell'istruzione stessa non possono essere catturati all'interno del withblocco.


1

Penso che tu abbia sbagliato sull'affermazione "con" che riduce solo le linee. Effettivamente esegue l'inizializzazione e gestisce lo smontaggio.

Nel tuo caso "con" fa

  • apri un file,
  • elaborare i suoi contenuti e
  • assicurati di chiuderlo.

Ecco il collegamento per comprendere l'istruzione "with": http://effbot.org/zone/python-with-statement.htm

Modifica: Sì, l'utilizzo di "con" è corretto e la funzionalità di entrambi i blocchi di codice è identica. Domanda sul perché usare "con"? è a causa dei vantaggi che ne derivano. come hai detto sulla mancanza accidentale di f.close ().


-4

Il modo più pitonico per i seguenti codici è:

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()

1
Ho aggiunto la formattazione del codice per te; lo rende più facile da leggere. Ma potresti voler ricontrollare per assicurarti di non aver rotto il rientro.
andrewsi

2
No, la tua versione non fa la stessa cosa del codice originale. Anche se aggiungi la readline()chiamata mancante , la tua versione non chiude il file se il readline()risultato è un IOError.
Aleksi Torhamo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.