2

我正在寻找一种可以将一些 Python 对象腌制到组合 tar 存档中的方法。此外,我还需要使用np.save(....)将一些 numpy 数组保存在同一个存档中。当然,我还需要稍后阅读它们。

所以我尝试的是

a = np.linspace(1,10,10000)    
tar = tarfile.open(fileName, "w")
tarinfo = tarfile.TarInfo.frombuf(np.save(a, fileName))
tar.close()

我得到了错误:

'numpy.ndarray' object has no attribute 'write'

如果我在 tar 文件中腌制一个对象,我会遇到类似的问题。有什么建议么?如果它更容易, json-pickle 也可以。

编辑:正如评论中提到的,我混淆了 np.save() 的参数。但是,这并不能解决问题,因为现在我收到错误:

object of type 'NoneType' has no len()

编辑2:如果上述问题没有解决方案,您是否知道任何其他有效时间绑定文件的方式?

4

1 回答 1

4

首先,我不是专家tar用户,但我可以指出几点:

 a = np.linspace(1,10,10000)    

 tar = tarfile.open(fileName, "w")

如果要将文件添加到现有文件,请使用“a”模式(或研究可用模式)。"w" 创建一个新的空白文件:

 tarinfo = tarfile.TarInfo.frombuf(np.save(a, fileName))

的正确使用np.save已经提到过。

TarInfo对象不是文件/数据,而是有关文件的信息。该信息位于数据之前的 tar 文件中,位于 512 字节的缓冲区中。 tobuf根据对象的属性创建这样的缓冲区。 frombuf解码这样的缓冲区。例如在fromtarfile方法中使用它:

def fromtarfile(cls, tarfile):
    """Return the next TarInfo object from TarFile object
       tarfile.
    """
    buf = tarfile.fileobj.read(BLOCKSIZE)
    obj = cls.frombuf(buf, tarfile.encoding, tarfile.errors)
    obj.offset = tarfile.fileobj.tell() - BLOCKSIZE
    return obj._proc_member(tarfile)

所以很明显frombuf不是你想在这里使用的。

A 2009 SO question - python write string directly to tarfile - 表明可以通过使用字符串缓冲区直接写入tarfile。从接受的答案:

# create a `StringIO` object, and fill it
string = StringIO.StringIO()
...
# create `TarInfo` object:
info = tarfile.TarInfo(name="foo")
info.size=len(string.buf)
# use both with `addfile`:
tar.addfile(tarinfo=info, fileobj=string)

我认为你可以做一个np.save缓冲StringIO,但我必须检查/测试才能确定。对于普通数组,save写入一个包含大小、形状、dtype 信息的标头,然后添加数组的数据缓冲区。对于其他对象和数组,它求助于pickle.

我建议np.save找一个常客,然后addfile工作。然后查看写入字符串缓冲区是否有效以及是否可以节省任何时间。


这是一个测试脚本。它将一个数组写入 tar 文件,关闭并重新打开文件并写入另一个数组,最后提取文件并加载它们。返回的形状看起来不错。我还没有研究是否可以将这些文件提取到内存缓冲区。

np.savez可以做同样的事情 zip 归档(而不是 tar)。

import numpy as np
import tarfile

import io   # python3 version
abuf = io.BytesIO()

np.save(abuf, np.arange(100))
abuf.seek(0)

tar=tarfile.TarFile('test.tar','w')
info= tarfile.TarInfo(name='anArray')
info.size=len(abuf.getbuffer())
tar.addfile(tarinfo=info, fileobj=abuf)
tar.close()

abuf = io.BytesIO()
np.save(abuf, np.ones((2,3,4)))
abuf.seek(0)

tar=tarfile.TarFile('test.tar','a')
info= tarfile.TarInfo(name='anOther')
info.size=len(abuf.getbuffer())
tar.addfile(tarinfo=info, fileobj=abuf)
tar.close()

tar=tarfile.TarFile('test.tar','r')
print(tar.getnames())
tar.extractall()
# can I extract to buffers?
tar.close()
a=np.load('anArray')
b=np.load('anOther')
print(a.shape, b.shape)

1415:~/mypy$ tar -tvf test.tar 
-rw-r--r-- 0/0             480 1969-12-31 16:00 anArray 
-rw-r--r-- 0/0             272 1969-12-31 16:00 anOther
于 2015-08-18T20:32:14.043 回答