Используя Python, как вы распаковываете себя в памяти?

Я работаю в среде, где я ничего не могу сохранить на диске. Мне нужно иметь возможность извлекать tar файлы и разархивировать их без сохранения на диск. Кажется, что это не работает:

Я пробовал это, но он бросает ошибки:

# fetch.py
from cStringIO import StringIO
import requests
url = "http://example.com/data.tar.gz"
response = requests.get(url)

# ERROR is thrown here. Error shown below
tar = tarfile.open(mode= "r:gz", fileobj = StringIO(response.content))

# This SHOULD break as tar.extract() saves to disk. 
# Can't tell because of error on previous line of code.
data = tar.extract() 

Как описано в приведенном выше блоке кода, я получаю следующую трассировку в строке ошибки:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "./importers/bestbuy_fetcher.py", line 23, in download_bestbuy_batch
    tar = tarfile.open(mode= "r:gz", fileobj = StringIO(response.content))
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/tarfile.py", line 1662, in open
    return func(name, filemode, fileobj, **kwargs)
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/tarfile.py", line 1711, in gzopen
    **kwargs)
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/tarfile.py", line 1689, in taropen
    return cls(name, mode, fileobj, **kwargs)
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/tarfile.py", line 1568, in __init__
    self.firstmember = self.next()
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/tarfile.py", line 2324, in next
    raise ReadError(str(e))
ReadError: invalid header

Оказывается, проблема заключалась в том, что файл data.tar.gz не был архивом tar. Просто сжатый файл gzip. Поэтому я решил его с помощью

# fetch.py
from cStringIO import StringIO
import gzip
import requests
# Called a 'tar' file but actually a gzip file. @#$%!!!
url = "http://example.com/data.tar.gz"
response = requests.get(url)

results = gzip.GzipFile(fileobj=StringIO(response.content))

Спасибо всем, кто помог вступить!

10
ответ дан 14 янв. '12 в 2:40
источник

Я подозреваю, что ошибка говорит вам, что формат файла tarfile неверен. Попробуйте извлечь файл с помощью wget и разблокировать его в командной строке.

Другой вопрос о том, как остановить Python, записывая содержимое файла на диск, требует более пристального изучения API tarfile. Вместо вызова TarFile.extract() я думаю, вам нужно getnames(), которое вернет имя каждого члена в файле tar. Затем вы можете использовать extractfile, чтобы получить содержимое этого члена:

 |  extractfile(self, member)
 |      Extract a member from the archive as a file object. `member' may be
 |      a filename or a TarInfo object. If `member' is a regular file, a
 |      file-like object is returned. If `member' is a link, a file-like
 |      object is constructed from the link target. If `member' is none of
 |      the above, None is returned.
 |      The file-like object is read-only and provides the following
 |      methods: read(), readline(), readlines(), seek() and tell()

Вот пример:

import tarfile    

# Open tarfile
tar = tarfile.open(mode="r:gz", fileobj = file('foo.tgz'))

# Iterate over every member
for member in tar.getnames():
    # Print contents of every file
    print tar.extractfile(member).read()
15
ответ дан 14 янв. '12 в 2:21
источник

Вы можете попробовать, что мы сделали, когда имеем дело с запросами + tar: используйте | чтобы открыть файл. Подробнее см. http://docs.python.org/library/tarfile.html#tarfile.open.

Вы можете увидеть код https://github.com/djeese/djeese-client/blob/master/djeese/commands/clonestatic.py#L53

В основном вы открываете tar файл с помощью tarfile.open(mode='r|gz', fileobj=response.raw).

Это чудесно работало для нас и, надеюсь, тоже для вас.

6
ответ дан 14 янв. '12 в 2:38
источник

Это должно помочь

import sys
import zipfile
sys.argv[0] = "/home/tom/Documents/REdata/AllListing1RES.zip"
zip_file    = zipfile.ZipFile(sys.argv[0])
items_file  = zip_file.open('AllListing1RES.txt', 'rU')
df = read_table(items_file, sep='\t', index_col=0)
2
ответ дан 14 янв. '12 в 2:19
источник