NamedTemporaryFile存在,但外部程序无法访问它

时间:2016-02-11 18:02:18

标签: python temporary-files blast

这是this question关于使用NamedTemporaryFile()

的排序的后续行动

我有一个创建和写入临时文件的函数。然后我想在另一个函数中使用该文件,该函数调用使用该文件的终端命令(该程序来自Blast +套件,blastn)。

def db_cds_to_fna(collection="genes"):  # collection gets data from mongoDB

    tmp_file = NamedTemporaryFile()
    # write stuff to file

    return tmp_file

def blast_all(blast_db, collection="genes"):        

    tmp_results = NamedTemporaryFile()    
    db_fna = db_cds_to_fna(collection) # should return another file object

    Popen(
        ['blastn',
         '-query', db_fna.name,
         '-db', blast_db,
         '-out', tmp_results.name,
         '-outfmt', '5']  # xml output
    )

    return tmp_results

当我致电blast_all时,我从blastn命令收到错误:

Command line argument error: Argument "query". File is not accessible:  `/var/folders/mv/w3flyjvn7vnbllysvzrf9y480000gn/T/tmpAJVWoz'

但是,就在Popen来电之前,如果我os.path.isfile(db_fna.name),则评估为True。我也可以做

print Popen(['head', db_fna.name]).communicate(0)

它正确地吐出文件的第一行。所以文件存在,并且它是可读的。此外,我使用相同的策略从同一个blast +套件中调用不同的程序(makeblastdb,请参阅顶部链接的问题)并且它可以工作。权限可能有问题吗?如果文件不存在,FWIW blastn会返回相同的错误,但很明显我正确地创建了文件,当我进行Popen调用时它是可读的,所以我很难过。

3 个答案:

答案 0 :(得分:1)

我在某个时候遇到了类似的问题。我正在寻找年龄,以为我永远不会找到原因。

就我而言,问题是由于文件系统延迟造成的。我想我最终使用time.sleep使用UIImageView来为文件系统提供一些时间来创建临时文件,然后再开始在子进程中访问它。

希望有所帮助!

答案 1 :(得分:1)

我相信我弄清楚了导致这种行为的事情。首先,Popen()函数通常不会等到外部命令完成后再继续它。其次,因为用户glibdud在我的其他问题中提到了in his answerNamedTemporaryFile就像TemporaryFile那样

  

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

由于我的blast_all()函数的末尾没有返回query临时文件,因此在外部blastn命令运行时它会被关闭并进行垃圾回收,因此文件将被删除。我猜测外部head命令的速度如此之快,以至于它没有遇到此问题,但blastn可能需要几分钟才能运行。

所以解决办法是迫使Popen()等待:

Popen(
    ['blastn',
     '-query', db_fna.name,
     '-db', blast_db,
     '-out', tmp_results.name,
     '-outfmt', '5']  # xml output
).wait()

答案 2 :(得分:1)

我认为问题可能是操作系统没有将文件同步到磁盘。写入文件描述符后,请执行以下操作:

tmp_file.flush()
os.fsync(tmp_file)

https://docs.python.org/3/library/os.html#os.fsync