genfromtxt:如何禁用缓存

Nam*_*ose 5 python numpy

我已经确认genfromtxt函数(以及从它派生的函数)以静默方式缓存它们在本地目录中处理的远程文件,并在后续调用中使用本地副本,而不检查它是否已更改.
通过查看源文件npyio.py,似乎发生这种情况是因为处理请求的DataSource对象是在不传递相关参数的情况下创建的.当然很容易修改库源来禁用缓存,但是每次升级后我都要重复它.
还有其他解决方案吗?(除了每次删除缓存目录)

Nam*_*ose 1

研究库源代码后,我意识到可以通过修改numpy数据源模块中名为open的小辅助函数的默认值来实现所需的行为。如上所述,无需修改库源即可实现此目的。这是我附带的代码:

import numpy
from numpy.lib._datasource import DataSource
#def open(path, mode='r', destpath=os.curdir):
def openm(path, mode='r', destpath=None):
  ds = DataSource(destpath)
  return ds.open(path, mode)
numpy.lib._datasource.open=openm
Run Code Online (Sandbox Code Playgroud)

在调用genfromtxt或从它派生的函数之前必须包含它。但我的研究进一步表明这些函数相当慢,并且在 Windows 中禁用缓存会产生警告 - 这不是由于上面的重新定义,它似乎与 Windows 中mktemp函数的实现
方式有关。此外,缓存的文件和关联的临时目录不会被删除。

这似乎与处理请求的数据源在读取和关闭文件之前超出范围(因此被删除)有关。当执行数据源的析构函数时,它尝试删除数据源的目录,由于文件句柄仍然打开,所以操作失败,因此出现警告。我正在考虑在 genfromtxt 函数中移动数据源实例化。 我确认在 genfromtxt 函数中移动数据源实例化在 Windows 和 Linux 下可以正常工作,因此我认为这是正确的解决方案。

我得出的结论是,最干净的方法是修改numpy库并将缓存参数添加到genfromtxt

以下是对 npyio.py 的必要修改,只需修改几行。genfromtxt 函数原型更改为

def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
           skiprows=0, skip_header=0, skip_footer=0, converters=None,
           missing='', missing_values=None, filling_values=None,
           usecols=None, names=None,
           excludelist=None, deletechars=None, replace_space='_',
           autostrip=False, case_sensitive=True, defaultfmt="f%i",
           unpack=None, usemask=False, loose=True, invalid_raise=True):
Run Code Online (Sandbox Code Playgroud)

to(添加新的缓存参数)

def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
           skiprows=0, skip_header=0, skip_footer=0, converters=None,
           missing='', missing_values=None, filling_values=None,
           usecols=None, names=None,
           excludelist=None, deletechars=None, replace_space='_',
           autostrip=False, case_sensitive=True, defaultfmt="f%i",
           unpack=None, usemask=False, loose=True, invalid_raise=True,cache=True):
Run Code Online (Sandbox Code Playgroud)

打开文件/url 的行从

if isinstance(fname, basestring):
    fhd = iter(np.lib._datasource.open(fname, 'rbU')
    own_fhd = True
Run Code Online (Sandbox Code Playgroud)

if isinstance(fname, basestring):
    ds=DataSource('.' if cache==True else None)
    fhd = iter(ds.open(fname, 'rbU'if cache==True else 'rbUD'))
    own_fhd = True
Run Code Online (Sandbox Code Playgroud)

“D”是 Windows 特定的打开标志(在 Linux 中无害),它标记文件临时,在文件句柄关闭时自动删除。
包装函数版本

def mgenfromtxt(fname,cache=True,**karg):
    if cache==False and isinstance(fname, basestring) and numpy.DataSource()._isurl(fname):
       ds=numpy.DataSource(None)
       fhd = iter(ds.open(fname,'rbUD'))
       l1=numpy.genfromtxt(fhd,**karg)
       fhd.close()
       del ds
       return l1
    else:
       return(numpy.genfromtxt(fname,**karg))  
Run Code Online (Sandbox Code Playgroud)