如何使用NamedTemporaryFile(什么时候关闭?)

时间:2016-02-05 15:56:20

标签: python python-2.7

我试图编写一系列写入临时文件的函数,然后使用写入的文件执行操作。我试图了解文件是如何处理的。

我想在摘要中做的是:

def create_function(inputs):
    # create temp file, write some contents

def function1(file):
    # do some stuff with temp file

def function2(file):
    # do some other stuff with temp file

所以我可以做类似的事情:

my_file = create_function(my_inputs)
function1(my_file)
function2(my_file)

所以这就是我实际做过的事情:

def db_cds_to_fna(collection, open_file):
    """
    This pulls data from a mongoDB and writes it to a temporary file - just writing an arbitrary string doesn't alter my question (I'm pretty sure)
    """
    for record in db[collection].find({"type": "CDS"}):
        open_file.write(">{}|{}|{}\n{}\n".format(
            collection,
            record["_id"],
            record["annotation"],
            record["dna_seq"]
            )
        )

    return open_file.name

def check_file(open_file):
    lines = 0
    for line in open_file:
        if lines < 5:
            print line
            lines += 1
        else:
            break

使用此代码,如果我运行以下内容:

from tempfile import NamedTemporaryFile
tmp_file = NamedTemporaryFile()
tmp_fna =  db_cds_to_fna('test_collection', tmp_file)

check_file(tmp_file)

此代码运行,但实际上并未打印任何内容。但是文件显然是在那里写的,因为如果我运行print Popen(['head', tmp_fna], stdout=PIPE)[0],我会得到文件的预期开头。或者,如果我更改check_file()以接受tmp_file.name并在函数内执行with open(tmp_file.name, 'r')...,则可行。

所以问题1是 - 为什么我可以写tmp_file,但是不能重新打开它就能从不同的函数中读取它?

现在,我真正想做的是在tmp_file = NamedTemporaryFile()函数中使用db_cds_to_fna(),但是当我尝试并运行时:

tmp_fna =  db_cds_to_fna('test_collection')
check_file(tmp_file)

我收到错误No such file or folder

所以问题2是:有没有办法保留临时文件以供另一个函数使用?我知道如何将文件写入指定的路径然后将其删除,但我怀疑是否有内置的方法可以做到这一点,我想学习。

1 个答案:

答案 0 :(得分:1)

您正在写入该文件,但之后您正在尝试从写入结束时读取它。在开始阅读之前添加seek,以返回文件的开头:

def check_file(open_file):
    lines = 0
    open_file.seek(0)
    for line in open_file:
        if lines < 5:
            print line
            lines += 1
        else:
            break

关于第二个问题,请注意NamedTemporaryFile的作用类似于TemporaryFile

  

它会在关闭时被销毁(包括隐含的   当对象被垃圾收集时关闭。)

如果在函数中打开文件然后返回,则文件超出范围并将被关闭并进行垃圾回收。您需要保持对文件对象的引用,以防止它被收集。您可以通过从函数返回文件对象来执行此操作(并确保将其分配给某些内容)。这是一个简单的例子:

def mycreate():
    return NamedTemporaryFile()
def mywrite(f, i):
    f.write(i)
def myread(f):
    f.seek(0)
    return f.read()

f = mycreate()        # 'f' is now a reference to the file created in the function, 
                      # which will keep it from being garbage collected
mywrite(f, b'Hi')
myread(f)