2009-10-26 250 views
1

我已经将IOError处理移动到一个单独的函数,以避免打开文件读取样板。如何避免重复异常处理?

但是,如果IOError在读取文件时触发?如果sshfs断开连接,或者文件被root等删除?

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) 

文件是只读方式不同,所以我不明白的方式把它放到功能,通过不断变化的部分作为参数。

[新增:想到这个解决方案,但它使一个发电机不能关闭。如果循环停止,该文件是开放的。]

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 

回答

7

我可能会尝试移动文件操作成单独的功能和包装那些一试...除了

其实我只是得到了一个甚至更好的主意......把错误处理成装饰和装饰应用到每一个,做文件操作

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

,那么你可以把所有的文件OPS到自己的功能和应用的装饰功能

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

,或者如果您需要兼容的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

与装饰好主意!没想到它。 – 2009-10-26 12:56:21

+0

很好用的装饰。总是寻找一个很好的例子来销售它们:-) – 2009-10-26 13:38:19

+0

对于2.3的实际特性比较,你必须摆脱“with”的使用。 :) – jamessan 2009-10-30 16:40:33