如何避免异常处理的重复?

1 投票
1 回答
607 浏览
提问于 2025-04-15 15:23

我把处理输入输出错误的部分移到了一个单独的函数里,这样在打开文件进行读取时就不用重复写很多相似的代码。

但是,如果在读取文件的时候发生了输入输出错误怎么办?比如说,sshfs断开连接了,或者文件被管理员删除了等等。

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

1 个回答

7

我可能会尝试把文件操作放到单独的函数里,然后用try...except来处理可能出现的错误。

其实我刚想到一个更好的主意……把错误处理放到一个装饰器里,然后把这个装饰器应用到每个进行文件操作的函数上。

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

这样你就可以把所有的文件操作放到自己的函数里,然后应用这个装饰器。

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

撰写回答