2009-10-26 7 views
1

J'ai déplacé la gestion d'IOError vers une fonction distincte pour éviter les erreurs lors de l'ouverture des fichiers à lire.Comment éviter la répétition du traitement des exceptions?

Mais que se passe-t-il si IOError se déclenche lors de la lecture du fichier? Si sshfs se déconnecte, ou si le fichier est supprimé par root, etc.

def safe_open(*args): 
    try: 
     return open(*args) 
    except IOError: 
     quit('Error when opening file \'{0}\'. Error #{1[0]}: {1[1]}'.format(\ 
     args[0], sys.exc_info()[1].args)) 

...

with safe_open(myfile, 'r') as f: 
    for i in f: 
     print i 

with safe_open(anotherfile, 'r') as f: 
    try: 
     conf = ''.join(f).format(**args) 
    except KeyError: 
     quit('\nOops, your template \'{0}\' has placeholders for' + \ 
     'parameters\nthat were not supplied in the command line: - {1}\n' + 
     '\nCan\'t proceed. Ending. Nothing has been changed yet.'.format(\ 
     args['host_template'], '\n - '.join(sys.exc_info()[1].args)), 1) 

fichier est lu de différentes manières, donc je ne vois pas un moyen de le mettre dans la fonction et de passer la partie changeant comme arguments.

[Ajouté: pensé à cette solution, mais il fait un générateur qui ne peut pas être fermé. Si une boucle est arrêtée, le fichier reste ouvert.]

def reader(*args): 
    try: 
     with safe_open(*args) as f: 
      for i in f: 
       yield i 
    except IOError: 
     print('IOError when trying to read \'{0}\''.format(args[0])) 

for i in reader(myfile, 'r'): 
    pass # do some job 

Répondre

7

Je probablement essayer de déplacer les opérations de fichiers dans des fonctions distinctes et envelopper celles essayer ... sauf

en fait je viens de recevoir un meilleure idée ... mettre l'erreur de manipulation dans un décorateur et d'appliquer le décorateur à chacune des fonctions qui effectue des opérations de fichiers

def catch_io_errors(fn): 
    def decorator(*args, **kwargs): 
     try: 
      return fn(*args, **kwargs) 
     except IOError: 
      quit('whatever error text') 
    return decorator 

alors vous pouvez mettre toutes les opérations de fichiers dans leurs propres fonctions et d'appliquer le décorateur

@catch_io_errors 
def read_file(): 
    with open(myfile, 'r') as f: 
     for i in f: 
      print i 

ou si vous avez besoin de compatibilité avec Python 2.3:

def read_file(): 
    f = open(myfile, 'r') 
    for i in f: 
     print i 
    f.close() 

read_file = catch_io_errors(read_file) 
+0

Bonne idée avec décorateurs! Je n'y ai pas pensé. –

+0

Joli usage de décorateurs. Toujours à la recherche d'un bon exemple pour les vendre :-) –

+0

Pour la parité réelle avec 2.3, vous devriez vous débarrasser de l'utilisation de "avec". :) – jamessan

Questions connexes