【问题标题】:Write data directly to a tar archive将数据直接写入 tar 存档
【发布时间】:2015-08-18 13:42:57
【问题描述】:

我正在寻找一种可以将一些 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 也可以。

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

object of type 'NoneType' has no len()

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

【问题讨论】:

  • 一方面,np.save 的参数是错误的。第一个需要是打开的文件对象或字符串,但你给它a,这是一个np.ndarray
  • 谢谢!我编辑了问题
  • np.save 返回None
  • 我不确定是否有办法“直接”写入tar 文件,尽管您当然可以将数组保存到中间文件,然后将其添加到存档中(即使用tar.add())。
  • np.savez 可用于在单个压缩存档中保存多个 numpy 数组。它还将接受任意 Python 对象,这些对象将被转换为 dtype np.object 的数组,因此被腌制。

标签: python numpy pickle tar jsonpickle


【解决方案1】:

首先,我不是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 信息的 header,然后添加数组的数据缓冲区。对于其他对象和数组,它求助于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

【讨论】:

    猜你喜欢
    • 2023-03-13
    • 2011-10-31
    • 2015-05-09
    • 1970-01-01
    • 1970-01-01
    • 2020-03-25
    • 1970-01-01
    • 2018-04-15
    • 1970-01-01
    相关资源
    最近更新 更多