Numpy savez例外

时间:2016-03-07 04:13:06

标签: python python-2.7 numpy io save

我最近发现了这个声明:

  

np.savez不是多进程安全的,因为它总是使用   gettempdir()+ key +“。npy”。所以,如果你正在运行相同的脚本   通过不同的数据集,您可以在一个数据集中使用自己的数据   process删除另一个进程的/tmp/arr_0.npy。

     

幸运的是,我处于这种情况,所以我有一个   示例错误:

Traceback (most recent call last):    File
"/home/pedro/prospectus/prelim/bbvs/bin/skldthresh", line 99, in <module> main()    
File "/home/pedro/prospectus/prelim/bbvs/bin/skldthresh", line 90, in  main
 np.savez("%smask-t%0.2f" % (outfile,threshold), result)    
File "/usr/lib/python2.5/site-packages/numpy/lib/io.py", line 230, in savez
 zip.write(filename, arcname=fname)    
 File "/usr/lib/python2.5/zipfile.py", line 541, in write
  st = os.stat(filename)  OSError: [Errno 2] No such file or directory: '/tmp/arr_0.npy'
     

幸运的是,将tempfile.gettempdir()替换为tempfile.mkdtemp()   并记住最后使用os.rmdir(direc)进行清理就是这样   据我所知,它会修复它。

这究竟意味着什么?我个人如何避免这种情况? numpy是否将写入.npz文件的数据存储在临时文件中,这些文件可能像其他脚本中的其他临时.npz文件一样命名?!

我有一些科学实验经过几个小时,并通过np.savez保存结果。使用savez保存的结果的目标路径不同,因此每个实验都有自己的结果路径。但是,它们脚本本身位于同一目录中。

有趣的是,脚本有时会在发生此错误前几个小时运行:

> Traceback (most recent call last):   File
> "/work/var/slurmd/state.node348.d/job20832/slurm_script", line 53, in
> <module>
>     E = Exp6_06()   File
> "/work/experiments/s06/cs06_ex06.py", line
> 150, in __init__
>     self.__start()   File "/work/experiments/s06/cs06_ex06.py", line
> 374, in __start
>     File "/home/fx092/.local/lib/python2.7/site-packages/numpy/lib/npyio.py",
> line 600, in savez_compressed
>     _savez(file, args, kwds, True)   File "/home/fx092/.local/lib/python2.7/site-packages/numpy/lib/npyio.py",
> line 630, in _savez
>     fd, tmpfile = tempfile.mkstemp(suffix='-numpy.npy')   File "/sw/env/openmpi/2Q4/lib/python2.7/tempfile.py",
> line 314, in mkstemp
>     return _mkstemp_inner(dir, prefix, suffix, flags)   File "/sw/env/openmpi/2Q4/lib/python2.7/tempfile.py",
> line 244, in _mkstemp_inner
>     fd = _os.open(file, flags, 0600) OSError: [Errno 2] No such file or directory:
> '/work/tmp/node001.admin.2016-03-06-152506.fx092.27432/tmp5UulEz-numpy.npy'

使用过的numpy版本:1.10.4

1 个答案:

答案 0 :(得分:1)

您的错误发生在mkstemp。引用建议使用mkdtemp代替:

https://docs.python.org/2/library/tempfile.html

  

tempfile.mkstemp([suffix =&#39;&#39; [,prefix =&#39; tmp&#39; [,dir = None [,text = False]]]])

     

以最安全的方式创建临时文件。假设平台正确实现os.open()的os.O_EXCL标志,文件创建中没有竞争条件。该文件只能由创建用户ID读写。如果平台使用权限位来指示文件是否可执行,则该文件可由任何人执行。子进程不会继承文件描述符。

  

tempfile.mkdtemp([suffix =&#39;&#39; [,prefix =&#39; tmp&#39; [,dir = None]]])

     

以最安全的方式创建临时目录。目录的创建中没有竞争条件。该目录只能通过创建用户ID进行读取,写入和搜索。

     

mkdtemp()的用户负责在完成后删除临时目录及其内容。

引用的错误似乎在创建临时文件后发生,并且它们被收集到zip中。创建其中一个临时文件时,似乎发生了错误。

我还没有充分利用这些功能来理解差异。  我们可能需要在_savez中学习lib/npyio.py

您使用的操作系统是什么? Linux,mac,windows?

此处是_savez的核心,现在位于lib/npyio.py文件中:

def _savez(file, args, kwds, compress):
    ....
    zip = zipfile_factory(file, mode="w", compression=compression)

    # Stage arrays in a temporary file on disk, before writing to zip.
=>  fd, tmpfile = tempfile.mkstemp(suffix='-numpy.npy')
    os.close(fd)
    try:
        for key, val in namedict.items():
            fname = key + '.npy'
            fid = open(tmpfile, 'wb')
            try:
                format.write_array(fid, np.asanyarray(val))
                fid.close()
                fid = None
=>              zip.write(tmpfile, arcname=fname)
            finally:
                if fid:
                    fid.close()
    finally:
        os.remove(tmpfile)
    zip.close()

引用的错误发生在循环结束时,当临时保存&#39;文件已添加到存档中。当您获取临时目录和临时文件(fd)时,您的错误会提前发生。请注意,丢弃打开的文件句柄,只使用名称(对每个数组重复使用)。

令人惊讶的是,mkstemp函数调用期间临时目录应该已经消失了。这几乎感觉像openmpi问题,而不是savez问题。