2012-01-13 33 views
22

Tôi đang làm việc trong môi trường mà tôi không thể lưu bất kỳ thứ gì vào đĩa. Tôi cần để có thể kéo các tập tin tar và giải nén chúng mà không cần lưu vào đĩa. Điều này dường như thất bại:Sử dụng Python, làm thế nào để bạn hoàn toàn thoát khỏi bộ nhớ?

Tôi đã thử điều này, nhưng nó tung lỗi:

# 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() 

Như đã trình bày trong khối mã trên tôi nhận được traceback sau trên dòng lỗi:

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 
+0

Bạn nhận được lỗi đó vì 'response.content' không phải là tệp tar được nén gzip hợp lệ – geoffspear

+0

Điều đó có ý nghĩa: Vậy làm cách nào để biến nó thành tệp tar được nén gzip hợp lệ? – pydanny

+0

Làm việc với tôi một tar.gz hợp lệ được phục vụ từ localhost Bạn chỉ có thể nhận được một tarball xấu. – codysoyland

Trả lời

10

Hóa ra vấn đề là các tập tin "data.tar.gz không phải là một kho lưu trữ tar Chỉ cần một file gzip nén Vì vậy, tôi giải quyết nó với:..

# 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)) 

Nhờ mọi người giúp pitch in!

+23

** Đây không phải là câu trả lời cho câu hỏi được đặt ra trong tiêu đề, do đó rất khó hiểu đối với những người đọc muốn giải quyết các vấn đề tương tự. ** – nealmcb

2

Điều này cần giúp đỡ

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

Thật không may, yêu cầu không có quyền truy cập đĩa. ;) – pydanny

+0

Vấn đề là việc sử dụng zipfile ở đâu, là phi vật chất nhưng bạn cần biết tệp nào trong kho lưu trữ mà bạn đang tìm kiếm. – dartdog

15

Tôi nghi ngờ lỗi này cho bạn biết rằng định dạng tệp của tarfile là sai. Hãy thử tìm nạp tệp bằng wget và hủy tệp đó trên dòng lệnh.

Câu hỏi khác, về cách dừng Python ghi nội dung tệp vào đĩa yêu cầu xem xét kỹ hơn API tarfile. Thay vì gọi số TarFile.extract() Tôi nghĩ bạn cần getnames() sẽ trả về tên của mọi thành viên trong tệp tar. Sau đó, bạn có thể sử dụng extractfile để có được những nội dung của thành viên đó:

| 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's 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() 

Dưới đây là một ví dụ:

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() 
+0

Vâng, tar -zxvf data.tar.gz ném định dạng lưu trữ "tar: Không được công nhận định dạng: Loại tệp hoặc định dạng không phù hợp". Đang cố gắng tìm ra nơi mọi thứ đang đi sai vì tôi có thể mở từ một cửa sổ nhưng không phải là dòng lệnh. : P – pydanny

+0

Rõ ràng là tôi đã bị sai cờ. gzip -d data.tar.gz hoạt động tốt. Bây giờ cố gắng tìm ra lý do tại sao tarfile của Python không chơi tốt. – pydanny

+0

Điều đó thật kỳ quặc bởi vì tôi đã sử dụng cùng một cờ như bạn và nhận được kết quả tích cực ... – snim2

6

Bạn có thể thử những gì chúng ta đã làm khi đối phó với các yêu cầu + tar: Sử dụng | để mở tệp. Xem http://docs.python.org/library/tarfile.html#tarfile.open để biết chi tiết.

Bạn có thể xem mã tại https://github.com/djeese/djeese-client/blob/master/djeese/commands/clonestatic.py#L53

Về cơ bản bạn mở file tar sử dụng tarfile.open(mode='r|gz', fileobj=response.raw).

Điều đó làm việc tuyệt vời cho chúng tôi và hy vọng bạn cũng vậy.

+0

Đã cố gắng nhưng không thành công vì khách hàng đang cung cấp tệp gzip giả vờ là một con tarfile. Sự cố được khắc phục bằng cách sử dụng giải pháp gzip thuần túy. :) – pydanny

Các vấn đề liên quan