2012-04-19 30 views
15

Tôi đang phân tích tệp 20Gb và xuất các dòng đáp ứng một điều kiện nhất định cho tệp khác, tuy nhiên thỉnh thoảng python sẽ đọc trong 2 dòng cùng một lúc và nối chúng.Phân tích tệp văn bản lớn (20GB) bằng python - đọc theo 2 dòng là 1

inputFileHandle = open(inputFileName, 'r') 

row = 0 

for line in inputFileHandle: 
    row = row + 1 
    if line_meets_condition: 
     outputFileHandle.write(line) 
    else: 
     lstIgnoredRows.append(row) 

Tôi đã kiểm tra kết thúc dòng trong tệp nguồn và kiểm tra dưới dạng nguồn cấp dữ liệu dòng (ascii char 10). Kéo ra các hàng vấn đề và phân tích cú pháp chúng trong sự cô lập hoạt động như mong đợi. Tôi có ấn một số giới hạn python ở đây không? Vị trí trong tập tin bất thường đầu tiên là khoảng mốc 4GB.

+0

có bất thường nắm tay luôn luôn xảy ra nhất quán với cùng một dòng không? Ngoài ra, là 'lstIgnoredRows' một danh sách, lớn như thế nào mà phát triển? Tôi tự hỏi điều gì sẽ xảy ra nếu bạn chỉ lưu các dòng bạn quan tâm đến tệp đầu ra và không làm bất cứ điều gì với các dòng bạn muốn bỏ qua. – Levon

+1

Có lẽ bạn có thể thử đọc từng phần nhỏ của tệp tại một thời điểm bằng cách sử dụng một phương thức lười biếng, tương tự như câu hỏi này? Cung cấp cho nó một shot http://stackoverflow.com/questions/519633/lazy-method-for-reading-big-file-in-python – prrao

+0

Nó xảy ra ở cùng một dòng đếm mỗi lần. lstIgnoredRows có thể phát triển đến vài nghìn mục. – James

Trả lời

23

nhanh tìm kiếm google cho "trăn đọc các file lớn hơn 4gb" mang lại nhiều kết quả nhiều. Xem here for such an exampleand another one which takes over from the first.

Đó là lỗi trong Python.

Bây giờ, giải thích về lỗi; nó không dễ tái tạo bởi vì nó phụ thuộc cả vào kích thước bộ đệm FILE nội bộ và số ký tự được chuyển tới fread(). Trong mã nguồn CRT của Microsoft, trong open.c, có một khối bắt đầu với nhận xét đáng khích lệ này "Đây là phần khó khăn. Chúng tôi tìm thấy CR ở cuối bộ đệm. Chúng tôi phải xem trước để xem liệu char tiếp theo có phải là LF hay không . " Thật kỳ lạ, có một bản sao gần như chính xác của chức năng này trong mã nguồn Perl: http://perl5.git.perl.org/perl.git/blob/4342f4d6df6a7dfa22a470aa21e54a5622c009f3:/win32/win32.c#l3668 Sự cố trong lệnh gọi hàm SetFilePointer(), được sử dụng để lùi lại một vị trí sau khi tìm kiếm; nó sẽ thất bại vì nó không thể trả về vị trí hiện tại trong DWORD 32 bit. [Sửa chữa rất dễ dàng; Bạn có thấy nó không?] Tại thời điểm này, hàm này cho rằng lần đọc tiếp theo() sẽ trả về LF, nhưng nó sẽ không vì con trỏ tệp không được di chuyển trở lại.

Và công việc xung quanh:

Nhưng lưu ý rằng Python 3.x không bị ảnh hưởng (file nguyên gốc luôn mở trong chế độ nhị phân và CRLF dịch được thực hiện bằng Python); với 2,7, bạn có thể sử dụng io.open().

+1

Mở tệp ở chế độ nhị phân đã khắc phục sự cố này.Cảm ơn sự giúp đỡ của bạn mở (inputFileName, 'rb') – James

+0

mở ở chế độ nhị phân cũng đã giải quyết nó cho tôi, đây là trình tiết kiệm cuộc sống! – tlamadon

7

Dấu 4GB đáng ngờ gần giá trị lớn nhất có thể được lưu trữ trong thanh ghi 32 bit (2 ** 32).

Mã bạn đã đăng có vẻ tốt, vì vậy tôi sẽ nghi ngờ một lỗi trong bản dựng Python của bạn.

FWIW, đoạn sẽ là một chút bụi nếu nó được sử dụng liệt kê:

inputFileHandle = open(inputFileName, 'r') 

for row, line in enumerate(inputFileHandle): 
    if line_meets_condition: 
     outputFileHandle.write(line) 
    else: 
     lstIgnoredRows.append(row) 
Các vấn đề liên quan