2013-02-26 28 views
5

Giả sử tôi có một tệp BIG với một số dòng tôi muốn bỏ qua và hàm (file_function) có đối tượng tệp. Tôi có thể trả về một đối tượng tệp mới có dòng đáp ứng một số điều kiện mà không đọc toàn bộ tệp đầu tiên, điều này là laziness là phần quan trọng.Lười biếng lọc một tập tin trước khi đọc

Lưu ý: Tôi chỉ có thể lưu một tệp tạm thời với những dòng này bị bỏ qua, nhưng điều này không lý tưởng.

Ví dụ, giả sử tôi có một tập tin csv (với một đường xấu):

1,2 
ooops 
3,4 

Một nỗ lực đầu tiên là tạo ra đối tượng tập tin mới (với cùng một phương pháp như tập tin) và ghi đè lên readline:

class FileWithoutCondition(file): 
    def __init__(self, f, condition): 
     self.f = f 
     self.condition = condition 
    def readline(self): 
     while True: 
      x = self.f.readline() 
      if self.condition(x): 
       return x 

Điều này hoạt động nếu file_name chỉ sử dụng readline ... nhưng không nếu nó yêu cầu một số chức năng khác.

with ('file_name', 'r') as f: 
    f1 = FileWithoutOoops(f, lambda x: x != 'ooops\n') 
    result = file_function(f1) 

Một giải pháp sử dụng StringIO có thể làm việc, nhưng tôi dường như không thể làm cho nó.

Lý tưởng nhất chúng ta nên giả định rằng file_function là chức năng hộp đen, cụ thể là tôi không thể tinh chỉnh nó để chấp nhận máy phát (nhưng có thể tôi có thể tinh chỉnh trình tạo thành tệp như thế nào?).
Có cách nào tiêu chuẩn để làm kiểu đọc lười biếng (đọc lướt) của một tệp chung không?

Lưu ý: ví dụ thúc đẩy cho câu hỏi này là this pandas question, nơi chỉ có một readline là không đủ để có được pd.read_csv làm việc ...

+2

Tôi nghĩ bạn cần phải làm rõ cho chúng tôi chính xác những yêu cầu về đối tượng "tệp" là gì. Nếu nó cần nhiều hơn chỉ là khả năng tạo ra dòng, chúng ta cần phải biết những gì khác. –

+0

@JohnZwinck Tôi nghĩ rằng bạn có thể đúng, tôi đã hy vọng có thể có một số cách chung chung để làm điều này (mà sẽ làm việc với bất kỳ "tập tin". Có lẽ đây là ngây thơ ... –

+1

Có lẽ. :) Kiểm tra http: // stackoverflow.com/questions/5335017/what-is-the-minimal-subset-of-file-methods-i-need-to-implement-to-get-the-full-p nếu bạn chưa có. –

Trả lời

1

Sử dụng một cách tiếp cận bản đồ giảm với các cơ sở Python hiện có. Trong ví dụ này tôi đang sử dụng một biểu thức chính quy cho phù hợp với dòng bắt đầu bằng chuỗi GET /index, nhưng bạn có thể sử dụng bất cứ điều kiện phù hợp với hóa đơn của bạn:

import re 
from collections import defaultdict 

pattern = re.compile(r'GET /index\(.*\).html') 

# define FILE appropriately. 
# map 
# the condition here serves to filter lines that can not match. 
matches = (pattern.search(line) for line in file(FILE, "rb") if 'GET' in line) 
mapp = (match.group(1) for match in matches if match) 

# now reduce, lazy: 
count = defaultdict(int) 
for request in mapp: 
    count[request] += 1 

này quét a> tập tin 6GB trong một vài giây trên máy tính xách tay của tôi . Bạn có thể chia nhỏ một tệp thành nhiều phần và cho chúng vào các luồng hoặc các tiến trình. Sử dụng mmap Tôi không khuyên bạn trừ khi bạn có bộ nhớ để ánh xạ toàn bộ tệp (nó không hỗ trợ cửa sổ).

+0

Đây không phải là một máy phát điện chứ không phải là tập tin? Tương tự như câu trả lời (đã xóa) bên dưới? –

+0

Đó có phải là vấn đề không? Bạn có thể bọc trình tạo 'mapp = ...' trong lớp ''readline' giống như tệp của bạn và thu được từ nó, nhưng tôi sẽ không làm điều đó, bởi vì không có lớp trừu tượng cho một tệp, vì vậy bạn phải triển khai tất cả các phương thức . –

+0

có lẽ không có lớp trừu tượng cho một tập tin là vấn đề, tôi đã hy vọng tôi chỉ có thể giả vờ nó là một tập tin. [Ví dụ thúc đẩy] (http://stackoverflow.com/questions/15088190/what-is-the-easiest-way-to-load-a-filtered-tda-file-using-pandas) có 'file_function = pd. read_csv' (cần nhiều hơn readline). :( –

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