Numpy savez 异常

Posted

技术标签:

【中文标题】Numpy savez 异常【英文标题】:Numpy savez exceptions 【发布时间】:2016-03-07 04:13:06 【问题描述】:

我最近发现了这个说法:

np.savez 不是多进程安全的,因为它总是使用 gettempdir() + 键 + “.npy”。因此,如果您正在运行相同的脚本 在不同的数据集上,您将在一个 进程删除另一个进程的 /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

【问题讨论】:

npz 文件是 zip 存档。 savez 将每个变量保存在不同的文件中,然后将它们收集到存档中。 是的..如果多个进程同时工作,这意味着不同的脚本可能作用于同一个临时文件?! 请注意,您的报价已过时 --- savez 通常可以安全地并行使用。您收到的错误很可能是因为删除了目录/work/tmp/node001.admin.2016-03-06-152506.fx092.27432 --- 该目录来自您的运行时环境(通常是TMPDIR/TEMP 环境变量)。要查找的内容 --- 您自己的脚本是否删除了此目录,或者节点运行时环境在所有作业完成之前将其清理干净,或者可能存在一些 mpi 配置问题,其中创建了特定于作业的目录但只有其中一个它们被使用了吗? 【参考方案1】:

您的错误发生在mkstemp。引用建议改用mkdtemp

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

tempfile.mkstemp([suffix=''[, prefix='tmp'[, dir=None[, text=False]]]])

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

tempfile.mkdtemp([suffix=''[, prefix='tmp'[, dir=None]]])

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

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

在创建临时文件后出现引用的错误,并将它们收集到zip。创建临时文件之一时,您的错误似乎发生了。

我没有充分使用这些函数来理解其中的区别。 我们可能需要在lib/npyio.py 中研究_savez

您使用的是什么操作系统? 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()

引用的错误发生在循环结束时,将临时“保存”文件添加到存档中。当它获取临时目录和临时文件(fd)时,您的错误很早就发生了。请注意,丢弃打开的文件句柄,只使用名称(对每个数组重复)。

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

【讨论】:

我只使用 Linux。 好的,所以文件权限应该不是问题。

以上是关于Numpy savez 异常的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 numpy.savez 将带有子数组的数组保存到单独的 .npy 文件中

如何将字典和数组保存在同一个存档中(使用 numpy.savez)

(原+译)使用numpy.savez保存字典后读取的问题

numpy如何保存(存储)和读取数据?(.npy/.npz)np.save() np.savez() np.savetxt()

导入 Keras 会引发 numpy 异常

Numpy 和 PyTables 的浮点异常