2015-02-08 64 views
3

我想直接从谷歌云存储中读取压缩文件,并用Python csv包打开它们。 本地文件的代码如下:谷歌云存储的流式gzip文件

def reader(self): 
    print "reading local compressed file: ", self._filename 
    self._localfile = gzip.open(self._filename, 'rb') 
    csvReader = csv.reader(self._localfile, delimiter=',', quotechar='"') 
    return csvReader 

我曾与几个GCS的API(基于JSON,cloud.storage)出场,但他们都不给我的东西,我可以通过gzip的流。更重要的是,即使文件是未压缩的,我也无法打开文件并将其提供给cv.reader(Iterator类型)。

我的压缩CSV文件约为500MB,而未压缩的文件最多使用几GB。我认为这不是一个好主意:1 - 在打开它们之前在本地下载文件(除非我可以重叠下载和计算)或2 - 在计算之前将其完全打开到内存中。

最后,我当前在我的本地机器上运行这段代码,但最终我将移动到AppEngine,所以它也必须在那里工作。

谢谢!

+0

怎么样在多个部分分割您的档案? – Raito 2015-02-08 21:20:12

+0

这已经是1 + TB数据集的多个部分。 :D打破它似乎是一个不必要的想法。我正在尝试Alex Martelli的建议。 – user1066293 2015-02-11 07:33:55

回答

6

使用GCScloudstorage.open(filename, 'r')会给你一个只读类文件对象(前面创建类似但'w' :-)你可以同时使用,一大块,与标准Python库的zlib module,特别是zlib.decompressobj ,当然,如果GS对象最初是以互补的方式创建的(使用zlib.compressobj)。

另外,为了方便,你可以使用Python标准库的gzip module,e.g的阅读相类似:

当然
compressed_flo = cloudstorage.open('objname', 'r') 
uncompressed_flo = gzip.GzipFile(fileobj=compressed_flo,mode='rb') 
csvReader = csv.reader(uncompressed_flo) 

,反之为早期写作阶段。

注意,当你在本地运行(与dev_appserver),GCS系统客户端库使用本地磁盘文件模拟GCS - 在我的经验,这是很好的为发展宗旨,我可以使用gsutil或其他工具,当我需要与我的本地工作站上的“真实”GCS存储进行交互...当我需要GAE应用程序进行这种交互时(以及在本地首先开发GAE应用程序:-)时,GCS适用于此类应用程序。

+0

“当然,如果GS对象最初是以互补的方式创建的(使用zlib.compressobj)” - 为什么这个限制?这应该适用于任何有效的gzip文件内容,对吧?不是我测试过,但zlib模块的标题是“zlib - 与gzip **兼容的压缩**”;-)。 – 2015-02-08 21:48:26

+0

'gzip'添加'zlib'不知道也不关心的元数据,之后'gzip'用'zlib'压缩数据体,但仍然执行大量元数据工作,如crc维护。请参阅http://svn.python.org/projects/python/branches/py3k/Lib/gzip.py以获取'gzip.py'的源代码 - 在**'zlib'之上,有超过500行代码** ! - )当然,与GCS无关 - 请自行从本地磁盘文件转储/恢复,并且您将遇到相同的问题。最好,最简单,最聪明的:或者让'gzip'双向工作,或者如果元数据对你来说是无谓的包袱,'zlib'这两种方式(节省几个字节)。 – 2015-02-08 21:58:05

+0

我同意,为了简单起见,我们应该使用相同的工具。不过,我现在好奇zlib模块为什么声称“压缩与gzip兼容”,并在http://www.zlib.net上查看了文档。原来,*“gzip添加了zlib不知道也不关心的元数据”*并非真正正确。 'zlib'可以自动检测'gzip'封装(页眉+页脚),并可以忽略它,这取决于'windowBits'的设置。在Python中,这个特性也通过'zbits.decompressobj()''wbits'参数暴露出来。那很有意思。我已将示例代码添加到我的答案中。 – 2015-02-08 22:46:09

4

所以,你有gzipped文件存储在GCS上。您可以流式处理存储在GCS 上的数据。也就是说,您可以同时下载,解压缩和处理。这避免了

  • 有解压文件在磁盘上
  • 不得不等待,直到下载是能够处理数据之前完成。

gzip文件的具有小的页眉和页脚,和主体是压缩流时,由一系列的块,并且每个块是decompressable自身。 Python的zlib package可以帮助你!

编辑:这是如何解压缩和analzye一个ZLIB或gzip的流块,明智的,纯粹基于zlib示例代码:

import zlib 
from collections import Counter 


def stream(filename): 
    with open(filename, "rb") as f: 
     while True: 
      chunk = f.read(1024) 
      if not chunk: 
       break 
      yield chunk 


def decompress(stream): 
    # Generate decompression object. Auto-detect and ignore 
    # gzip wrapper, if present. 
    z = zlib.decompressobj(32+15) 
    for chunk in stream: 
     r = z.decompress(chunk) 
     if r: 
      yield r 


c = Counter() 
s = stream("data.gz") 
for chunk in decompress(s): 
    for byte in chunk: 
     c[byte] += 1 


print c 

我测试此代码用一个例子文件data.gz,创建与GNU gzip。从http://www.zlib.net/manual.html

行情:

windowBits也可以是大于15用于可选gzip的解码。添加 32到windowBits以启用zlib和gzip解码,自动搜索 标头,或者添加16以仅解码gzip格式(zlib 格式将返回Z_DATA_ERROR)。如果gzip流正在解码, strm-> adler是crc32而不是adler32。

的任何信息包含在gzip头不被保留[...]