将数据直接写入tar存档

时间:2015-08-18 13:42:57

标签: python numpy pickle tar jsonpickle

我正在寻找一种方法,可以将一些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:如果没有上述问题的解决方案,你知道其他任何时间有效绑定文件的方式吗?

1 个答案:

答案 0 :(得分: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不是你想在这里使用的。

2009年SO问题 - 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.saveStringIO缓冲区,但我必须检查/测试才能确定。对于普通数组,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