我已经确认,genfromtxt函数(以及从中派生的函数)将他们正在处理的远程文件悄悄地缓存在本地目录中,并在随后的调用中使用本地副本,而不检查它是否已更改。
通过查看源文件https://github.com/numpy/numpy/blob/v1.9.1/numpy/lib/npyio.py#L1180,这似乎是因为在没有传递相关参数的情况下创建了处理请求的DataSource对象。当然,修改库源代码以禁用缓存是很容易的,但是在每次升级之后,我必须重复这一点。
还有别的解决办法吗?(除了每次删除缓存目录外)
发布于 2015-05-15 09:40:18
通过对库源代码的研究,我意识到可以通过修改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它必须包括在调用genfromtxt或从中派生的函数之前。
但是我的研究进一步揭示了这些函数非常慢,并且在Windows中禁用缓存会产生一个警告--这不是由于上面的重新定义,它似乎与在Windows中实现mktemp函数的方式有关。此外,缓存的文件和相关的临时目录不会被删除。
这似乎与以下事实有关:处理请求的数据源在读取和关闭文件之前超出了作用域(因此被删除)。当执行数据源的析构函数时,它试图删除数据源的目录,操作失败,因为文件句柄仍然打开,所以警告。我正在考虑在genfromtxt函数中移动数据源实例化。我确认在和Linux下,在genfromtxt函数中移动数据源实例化是正确的,因此我认为这是一个合适的解决方案。
I得出的结论是,最干净的方法是修改 numpy 库,并从the 向 that添加缓存参数。
以下是对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):添加到(一个新的缓存参数)
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):打开文件/url的行更改为
if isinstance(fname, basestring):
fhd = iter(np.lib._datasource.open(fname, 'rbU')
own_fhd = True至
if isinstance(fname, basestring):
ds=DataSource('.' if cache==True else None)
fhd = iter(ds.open(fname, 'rbU'if cache==True else 'rbUD'))
own_fhd = TrueD‘是要打开的特定于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)) 发布于 2015-05-09 11:55:38
我认为这个问题其实由两部分组成:
genfromtxt的缓存行为?对于1.,包装(可能使用注入)比修补库更有弹性(除非补丁是上游完成的,在库的回购中)。
因此,包装genfromtxt可以如下所示:
def patched_gen_from_text(*args, **kwargs):
# Do something regarding caching
return numpy.genfromtxt(*args, **kwargs)您甚至可以在不修改源代码的情况下将其作为numpy.genfromtext注入(我并不推荐这样做):
import numpy
numpy.genfromtxt = patched_gen_from_text对于2.它实际上取决于您对远程文件系统的访问(例如,您能在那里运行一个过程吗?(你能安装它吗?),以及速度和确定性之间的权衡。
例如,在一个极端,您的修补版本可以无条件地删除本地文件(确定但缓慢)。或者,您可以请求远程文件的更新时间和长度,并查看它们如何与本地文件相对应。在另一个极端,您可能可以在另一台计算机上对RPC运行md5检查。
您可能需要检查卷曲是否有不同的比较选项,以及某些情况下可能存在的实际构建块。
https://stackoverflow.com/questions/30139451
复制相似问题