打开时打开的返回文件句柄?

时间:2015-03-03 06:13:18

标签: python with-statement

我正在创建我想接受压缩文件的软件。由于文件是在任何地方读/写的,我创建了一个实用程序函数来打开文件,处理打开/关闭对于某些压缩文件类型。

示例代码:

def return_file_handle(input_file, open_mode="r"):
    """ Handles compressed and uncompressed files. Accepts open modes r/w/w+ """

    if input_file.endswith(".gz")
        with gzip.open(input_file, open_mode) as gzipped_file_handle:
            return gzipped_file_handle

问题是,当使用此代码时,文件句柄似乎在函数返回时关闭。我可以用with open做我想做的事情,还是我需要处理自己的关闭?

将其添加到上面的代码中以获得最小的非工作示例:

for line in return_file_handle(input_bed, "rb"):
    print line

使用以下命令创建一个gzip压缩文本文件:

echo "hei\nder!" | gzip - > test.gz

错误讯息:

Traceback (most recent call last):
  File "check_bed_against_blacklist.py", line 26, in <module>
    check_bed_against_blacklist("test.gz", "bla")
  File "check_bed_against_blacklist.py", line 15, in check_bed_against_blacklist
    for line in return_file_handle(input_bed, "r"):
ValueError: I/O operation on closed file.

5 个答案:

答案 0 :(得分:12)

尝试将其作为生成器:

def return_file_handle(input_file, open_mode="r"):
""" Handles compressed and uncompressed files. Accepts open modes r/w/w+ """

    if input_file.endswith(".gz")
        with gzip.open(input_file, open_mode) as gzipped_file_handle:
            yield gzipped_file_handle

当你打电话时:

for line in return_file_handle("file.gz"):
    print line.read()

答案 1 :(得分:4)

我能想到的最好的方法是将一个函数作为接受打开的fd的参数传递:

def work(fd):
    for line in fd:
        print line

def work_with_file_handle(input_file, func, open_mode="r"):
   if input_file.endswith(".gz")
       with gzip.open(input_file, open_mode) as gzipped_file_handle:
           func(gzipped_file_handle)

work_with_file_handle('xxx.gz', work)

答案 2 :(得分:2)

用于打开文件的样式会在块结束时自动关闭它。这是打开文件的with块样式的重点。

您想要做的是:

gzipped_file_handle = gzip.open(input_file, open_mode)
return gzipped_file_handle

注意:在调用此函数后,您必须小心记住关闭文件。

答案 3 :(得分:2)

如果要返回file_handle,请避免使用。因为当块完成执行时,file_handle将自动关闭。

以下代码是你应该使用的:

import gzip
def return_file_handle(input_file, open_mode="rb"):
    if input_file.endswith(".gz"):
        gzipped_file_handle = gzip.open(input_file, open_mode)
        return gzipped_file_handle

for line in return_file_handle('file.txt.gz', "r"):
    print line

答案 4 :(得分:0)

我会使用另一个上下文管理器

from contextlib import contextmanager

@contextmanager
def return_file_handle(input_file, open_mode="r"):
    """ Handles compressed and uncompressed files. Accepts open modes r/w/w+ """

    if input_file.endswith(".gz")
        with gzip.open(input_file, open_mode) as gzipped_file_handle:
            yield gzipped_file_handle
    else:
        with open(input_file, open_mode) as normal_file:
            yield normal_file
    # Your file will be closed after this


with return_file_handle(file_name, mode) as f:
     pass