2015-02-08 2 views
3

Я хотел бы прочитать сжатые файлы непосредственно из Google Cloud Storage и открыть их с помощью пакета csv Python. Код для локального файла будет:потоковое gzipped файлы из облачного хранилища Google

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 

Я играл с несколькими API, ГКС (на основе JSON, cloud.storage), но ни один из них не кажется, чтобы дать мне то, что я могу течь через Gzip. Более того, даже если файл был несжатым, я не смог открыть файл и передать его в cv.reader (тип Iterator).

Мои сжатые CSV-файлы составляют около 500 МБ, в то время как несжатые они используют до нескольких ГБ. Я не думаю, что было бы неплохо: 1 - локально загружать файлы перед их открытием (если только я не могу перекрывать загрузку и вычисление) или 2 - полностью открывать его в памяти перед вычислением.

Наконец, я выполняю этот код на своей локальной машине, но в конечном итоге я перейду в AppEngine, так что он тоже должен работать.

Спасибо!

+0

насчет разделить файл на несколько частей? – Raito

+0

Это уже несколько частей набора данных 1 + TB. : D Ломать это еще больше кажется ненужной идеей. Я пытаюсь предложить Алекс Мартелли. – user1066293

ответ

6

Использование GCS, cloudstorage.open(filename, 'r') даст вам только для чтения файл-подобный объект (ранее созданный так же, но с 'w' :-), который вы можете использовать, кусок в то время, со стандартной библиотеки языка Python zlib module, конкретно zlib.decompressobj , если, конечно, объект GS первоначально был создан дополнительным образом (с zlib.compressobj).

Кроме того, для удобства, вы можете использовать стандартную библиотеку языка Python gzip module, например для фазы чтения что-то вроде:

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

и наоборот для более ранней стадии написания, конечно.

Обратите внимание, что при запуске локально (с dev_appserver), клиентская библиотека GCS использует локальные файлы диска для имитации ГКС - по моему опыту, что это хорошо для целей развития, и я могу использовать gsutil или другие инструменты, когда я необходимо взаимодействовать с «реальным» хранилищем GCS с моей локальной рабочей станции ... GCS - это то, когда мне нужно такое взаимодействие из моего приложения GAE (и для разработки приложения GAE локально в первую очередь :-).

+0

", если, конечно, объект GS первоначально был создан дополнительным способом (с zlib.compressobj)" - почему это ограничение? Это должно работать с любым допустимым содержимым файлов gzipped, не так ли? Не то, что я тестировал, но заголовок модуля zlib - «zlib - совместимость с компрессией ** с gzip **» ;-). –

+0

'gzip' добавляет метаданные, которые' zlib' не знает и не заботится - после чего 'gzip' сжимает тело данных с помощью' zlib', но все же выполняет много метаданных, таких как обслуживание crc. См. Http://svn.python.org/projects/python/branches/py3k/Lib/gzip.py для источников 'gzip.py' - более 500 строк кода ** поверх **' zlib' ! -) Разумеется, с GCS ничего общего - сделайте свой собственный сброс в/восстановление из файла локального диска, и у вас будут одинаковые проблемы. Самый лучший, самый простой, самый умный: либо «gzip» работать в обоих направлениях, либо, если мертвый багаж метаданных для вас, 'zlib' в обоих направлениях (сэкономить несколько байтов). –

+0

Я согласен, что для простоты нужно использовать один и тот же инструмент в обоих направлениях. Тем не менее, мне стало любопытно, почему модуль zlib утверждает, что «Compression совместим с gzip», и заглянул в документы на http://www.zlib.net. Оказывается, что * «gzip добавляет метаданные, которые zlib не знает и не заботится о» *, не совсем корректен. 'zlib' может автоматически определять оболочку' gzip' (header + footer) и может игнорировать ее в зависимости от параметра 'windowBits'. В Python эта функция также открывается через аргумент 'wbits' для' zlib.decompressobj() '. Это интересно. Я добавил пример кода к моему ответу. –

4

Итак, у вас есть файлы gzipped, хранящиеся на GCS. Вы можете обрабатывать данные, хранящиеся в GCS , потоковым способом. То есть вы можете загружать, распаковывать и обрабатывать одновременно. Это позволяет избежать

  • иметь распакованные файлы на диске
  • придется ждать, пока загрузка не будет завершена, прежде чем быть в состоянии обработать данные.

gzip-файлы имеют небольшой верхний и нижний колонтитул, а тело представляет собой сжатый поток, состоящий из серии блоков, и каждый блок декомпрессируется сам по себе. Python's zlib package помогает вам в этом!

Edit: Это пример кода для того, как распаковывать и 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 не сохраняется [...]

Смежные вопросы