Vấn đề ở đây không có gì để làm với gzip, và tất cả mọi thứ để làm với dòng đọc bởi dòng từ một tập tin 10GB không có dòng mới trong đó:
Là một lưu ý bổ sung, các tập tin tôi đã sử dụng để kiểm tra chức năng gzip Python được tạo ra bởi fallocate -l 10G bigfile_file.
Điều đó cung cấp cho bạn tệp có kích thước 10GB được tạo hoàn toàn bằng 0 byte. Có nghĩa là không có byte dòng mới. Có nghĩa là dòng đầu tiên dài 10GB. Có nghĩa là nó sẽ mất 10GB để đọc dòng đầu tiên. (Hoặc thậm chí có thể là 20 hoặc 40GB, nếu bạn đang sử dụng Python trước 3.3 và cố gắng đọc nó dưới dạng Unicode.)
Nếu bạn muốn sao chép dữ liệu nhị phân, đừng sao chép từng dòng. Cho dù đó là một tập tin bình thường, một GzipFile
đó là giải nén cho bạn trên bay, một socket.makefile()
, hoặc bất cứ điều gì khác, bạn sẽ có cùng một vấn đề.
Giải pháp là sao chép từng đoạn một.Hoặc chỉ sử dụng copyfileobj
, tự động thực hiện điều đó cho bạn.
import gzip
import shutil
with open('test_large.csv', 'rb') as f_in:
with gzip.open('test_out.csv.gz', 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)
Theo mặc định, copyfileobj
sử dụng một kích thước đoạn tối ưu hóa để được thường rất tốt và không bao giờ rất xấu. Trong trường hợp này, bạn có thể thực sự muốn có kích thước nhỏ hơn hoặc kích thước lớn hơn; thật khó để đoán trước được ưu tiên nào. * Vì vậy, hãy thử nghiệm nó bằng cách sử dụng timeit
với các đối số bufsize
khác nhau (giả sử, quyền hạn 4 từ 1KB đến 8MB) đến copyfileobj
. Tuy nhiên, 16KB mặc định có thể sẽ đủ tốt trừ khi bạn đang làm rất nhiều điều này.
* Nếu kích thước bộ đệm quá lớn, bạn có thể kết thúc luân phiên các đoạn dài của I/O và các đoạn xử lý dài. Nếu nó quá nhỏ, bạn có thể cần nhiều lần đọc để điền vào một khối gzip duy nhất.
Lỗi chính xác với giải pháp của Mark là gì? Nó không thể nằm trên 'f_out.writelines', vì bạn sử dụng' write' ... –
Lỗi sẽ như sau: 'Traceback (cuộc gọi gần đây nhất): File" test.py ", dòng 8, trong cho dòng trong f_in: MemoryError' –
shihpeng