1

我有一个(递归)函数,我想接受一个字符串或一个打开的文件对象。如果参数是字符串,则函数打开一个文件并使用该文件对象。当我从函数返回时,最好显式关闭这个打开的文件对象,但前提是传入了一个字符串。(想象一下当用户传入一个打开的文件对象并发现他们的文件对象在某个地方关闭时会感到惊讶)。这是我目前正在使用的:

def read_file(f, param):
    do_close = isinstance(f,basestring)
    f = open(f, 'rb') if do_close else f
    try:
        info = f.read(4)
        #check info here
        if info == Info_I_Want(param):
           return f.read(get_data(info))
        else:
           f.seek(goto_new_position(info))
           return read_file(f,param)
    except IKnowThisError:
           return None
    finally:
        if do_close:
           f.close()

IKnowThisError如果我找不到我想要的信息,您可以假设会在某个时候提出。

这感觉非常笨拙。有没有更好的办法?

4

3 回答 3

3

为什么不用包装器包装递归函数以避免开销?

def read_file(f, param):
    if isinstance(f, basestring):
        with open(f, 'rb') as real_f:
            return read_file2(real_f, param)
    else:
        return read_file2(real_f, param)

def read_file2(f, param):
    # Now f should be a file object
    ...
于 2012-08-02T13:28:48.093 回答
2

递归调用你的函数怎么样?

def read_file(f, param):
    if isinstance(f, basestring):
        with open(f, 'rb') as real_f:
            return read_file(real_f, param)
    else:
        # normal path
于 2012-08-02T13:25:56.887 回答
1

即将推出的 Python 3.3 为此类问题提供了更通用的解决方案,即contextlib.ExitStack. 这允许有条件地将上下文管理器添加到当前的 with 块:

def read_file(f, param):
    with ExitStack() as stack:
        if isinstance(f, basestring):
            f = stack.enter_context(open(f, 'rb'))
        # Your code here
于 2012-08-02T13:41:47.530 回答