2010-07-21 16 views
10

Tôi đang viết chương trình sẽ phân tích cú pháp tệp nhật ký Apache định kỳ để ghi lại khách truy cập, sử dụng băng thông, v.v.Python - Làm thế nào tôi có thể mở một tệp và chỉ định độ lệch theo byte?

Vấn đề là tôi không muốn mở nhật ký và phân tích cú pháp dữ liệu tôi đã đã được phân tích cú pháp. Ví dụ:

line1 
line2 
line3 

Nếu tôi phân tích cú pháp tệp đó, tôi sẽ lưu tất cả các dòng rồi lưu bù đắp đó. Bằng cách đó, khi tôi phân tích lại lần nữa, tôi nhận được:

line1 
line2 
line3 - The log will open from this point 
line4 
line5 

Vòng thứ hai, tôi sẽ lấy line4 và line5. Hy vọng điều này có ý nghĩa ...

Điều tôi cần biết là, làm cách nào để thực hiện việc này? Python có hàm seek() để xác định offset ... Vì vậy, tôi chỉ nhận được các tập tin của các bản ghi (theo byte) sau khi phân tích nó sau đó sử dụng đó như là bù đắp (trong tìm kiếm()) lần thứ hai tôi đăng nhập nó?

Tôi dường như không thể nghĩ ra cách để mã này>. <

Trả lời

13

bạn có thể quản lý các vị trí trong tập tin nhờ vào seektell phương thức của lớp file thấy https://docs.python.org/2/tutorial/inputoutput.html

Phương pháp tell sẽ cho bạn biết nơi để tìm kiếm lần sau khi bạn mở

+0

Điều này có vẻ như nó sẽ làm chính xác những gì tôi muốn. Chúc mừng. – dave

+1

Hmm, có vẻ như liên kết đó cần được cập nhật. Không có tham chiếu đến đối tượng tệp; Có lẽ: https://docs.python.org/2/tutorial/inputoutput.html – cevaris

1

Nếu log của bạn phù hợp một cách dễ dàng trong bộ nhớ (đây là, bạn có một chính sách luân chuyển hợp lý), bạn có thể dễ dàng làm điều gì đó như:

log_lines = open('logfile','r').readlines() 
last_line = get_last_lineprocessed() #From some persistent storage 
last_line = parse_log(log_lines[last_line:]) 
store_last_lineprocessed(last_line) 

Nếu bạn không thể làm được điều này, bạn có thể sử dụng một cái gì đó như (xem sử dụng được chấp nhận câu trả lời của tìm kiếm và nói, trong trường hợp bạn cần phải làm điều đó với họ) Get last n lines of a file with Python, similar to tail

+0

Nhật ký dành cho máy chủ ảo, vì vậy, hiện tại, không có xoay vòng nhật ký. Tôi cho rằng tôi nên xem xét việc thiết lập ... Điều này sẽ làm cho giải pháp của bạn khá hữu ích. Chúc mừng. – dave

0

Nếu bạn đang phân tích dòng nhật ký của bạn trên mỗi dòng, bạn có thể tiết kiệm Juste số dòng từ phân tích cuối cùng. Bạn sẽ có sau đó để bắt đầu đọc nó từ dòng tốt trong thời gian tới.

Tìm kiếm hữu ích hơn khi bạn phải ở một nơi rất cụ thể trong tệp.

0

dễ dàng nhưng không được khuyến khích :):

last_line_processed = get_last_line_processed()  
with open('file.log') as log 
    for record_number, record in enumerate(log): 
     if record_number >= last_line_processed: 
      parse_log(record) 
4
log = open('myfile.log') 
pos = open('pos.dat','w') 
print log.readline() 
pos.write(str(f.tell()) 
log.close() 
pos.close() 

log = open('myfile.log') 
pos = open('pos.dat') 
log.seek(int(pos.readline())) 
print log.readline() 

Tất nhiên bạn không nên sử dụng nó như thế - bạn nên quấn hoạt động trong các chức năng như save_position(myfile)load_position(myfile), nhưng chức năng là tất cả đó.

0

Lưu ý rằng bạn có thể tìm() trong python từ ngày kết thúc của tập tin:

f.seek(-3, os.SEEK_END) 

đặt vị trí đọc 3 dòng từ EOF.

Tuy nhiên, tại sao không sử dụng khác biệt, từ vỏ hoặc với difflib?

+3

Điều đó thực sự sẽ đặt vị trí đọc 3 ký tự từ EOF, chứ không phải 3 dòng. – Duncan

0

Dưới đây là mã chứng minh bằng cách sử dụng sugestion chiều dài của cậu và methond tell:

beginning="""line1 
line2 
line3""" 

end="""- The log will open from this point 
line4 
line5""" 

openfile= open('log.txt','w') 
openfile.write(beginning) 
endstarts=openfile.tell() 
openfile.close() 

open('log.txt','a').write(end) 
print open('log.txt').read() 

print("\nAgain:") 
end2 = open('log.txt','r') 
end2.seek(len(beginning)) 

print end2.read() ## wrong by two too little because of magic newlines in Windows 
end2.seek(endstarts) 

print "\nOk in Windows also" 
print end2.read() 
end2.close() 
0

Dưới đây là một đoạn hiệu quả và an toàn để làm điều đó tiết kiệm bù đắp đọc trong một tập tin parallell. Về cơ bản logtail trong python.

with open(filename) as log_fd: 
    offset_filename = os.path.join(OFFSET_ROOT_DIR,filename) 
    if not os.path.exists(offset_filename): 
     os.makedirs(os.path.dirname(offset_filename)) 
     with open(offset_filename, 'w') as offset_fd: 
      offset_fd.write(str(0)) 
    with open(offset_filename, 'r+') as offset_fd: 
     log_fd.seek(int(offset_fd.readline()) or 0) 
     new_logrows_handler(log_fd.readlines()) 
     offset_fd.seek(0) 
     offset_fd.write(str(log_fd.tell())) 
Các vấn đề liên quan