2013-02-22 12 views
38

Ho uno script in cui all'utente viene richiesto di digitare un nome file (di un file che deve essere aperto) e se il file non esiste nella directory corrente, l'utente viene richiesto nuovamente. Ecco la versione breve:"open()" di Python genera errori diversi per "file non trovato" - come gestire entrambe le eccezioni?

file = input("Type filename: ") 

... 
try: 
    fileContent = open(filename, "r") 
    ... 
except FileNotFoundError: 
    ... 

Quando ho provato il mio script sulla mia MacOS X in Python 3.3x ha funzionato perfettamente bene quando si digita il nome del file sbagliato di proposito (esegue la suite sotto "aspettarsi").

Tuttavia, quando volevo eseguire il mio codice su un computer Windows in Python 3.2x, viene visualizzato un errore che indica che "FileNotFoundError" non è definito. Quindi, Python 3.2 su Windows pensa che "FileNotFoundError" sia una variabile e che i programmi si chiudano con un errore.

Ho scoperto che Python 3.2 su Windows genera un "IOError" se il nome file di input non è valido. L'ho provato sulla mia macchina Linux in Python 2.7, ed è anche un IOError.

Il mio problema è ora, che il codice con

except "FileNotFoundError": 

non verrà eseguito su di Python 3.2 di Windows, ma se cambio a

except "IOError": 

non funzionerà sul mio Mac più.

Come posso aggirare? L'unico modo che posso pensare è quello di usare solo except, che di solito non voglio.

+6

Questo non è dovuto a Mac/Windows, è la * versione * di Python. Vorrei indagare su 3.2/3.3 anche su OS X (e 3.3 su Windows), consultare i log delle modifiche e quindi rivedere la domanda/titolo come appropriato. –

risposta

56

In 3.3, IOError became an alias for OSError, e FileNotFoundError è una sottoclasse OSError. Quindi si potrebbe provare

except (OSError, IOError) as e: 
    ... 

Ciò gettare una piuttosto ampia rete, e non si può assumere che l'eccezione è "File non trovato" senza ispezionare e.errno, ma potrebbe coprire il vostro caso d'uso.

PEP 3151 discute la motivazione del cambiamento in dettaglio.

2

si può prendere 2 errori al tempo stesso

except (FileNotFoundError, IOError):

Non mi rendevo conto che è quello che stavi chiedendo. Mi auguro che ci sia una soluzione più eloquente quindi di ispezionare manualmente

try: 
    error_to_catch = FileNotFoundError 
except NameError: 
    error_to_catch = IOError 

except error_to_catch

cwallenpoole fa questo condizionale più eloquente nella sua risposta (error_to_catch = getattr(__builtins__,'FileNotFoundError', IOError))

+2

Funzionerà dove - * Ricevo un errore che dice che "FileNotFoundError" non è definito. Quindi, Python 3.2 su Windows pensa che "FileNotFoundError" sia una variabile e che i programmi si chiudano con un errore * -? –

+0

@pst interessante scusa non lo considero – dm03514

7

Questo mi sembra meglio di un semplice except:, ma non sono sicuro se è la soluzione migliore:

error_to_catch = getattr(__builtins__,'FileNotFoundError', IOError) 

try: 
    f = open('.....') 
except error_to_catch: 
    print('!') 
+0

In altre notizie 'tranne:' seguito da una virgola è grammaticalmente corretto, ma sembra ancora molto strano. – cwallenpoole

+0

Questa è anche una soluzione molto bella. Un po 'più lungo di 'except (IOError, OSError):' ma quindi più specifico –

3

Quindi, per prendere esattamente solo quando un file non viene trovato, lo faccio:

import errno 
try: 
    open(filename, 'r') 
except (OSError, IOError) as e: # FileNotFoundError does not exist on Python < 3.3 
    if getattr(e, 'errno', 0) == errno.ENOENT: 
     ... # file not found 
    raise 
Problemi correlati