2015-02-08 62 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頭不被保留[...]