16

Apache ログ ファイルを定期的に解析して、訪問者や帯域幅の使用状況などを記録するプログラムを作成しています。

問題は、ログを開いて、既に解析したデータを解析したくないということです。例えば:

line1
line2
line3

そのファイルを解析すると、すべての行を保存してから、そのオフセットを保存します。そうすれば、もう一度解析すると、次のようになります。

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

2 回目は、line4 と line5 を取得します。うまくいけば、これは理にかなっています...

私が知る必要があるのは、どうすればこれを達成できるかということです。Python には、オフセットを指定する seek() 関数があります...ログを解析した後にファイルサイズ (バイト単位) を取得し、それを 2 回目にログに記録するときに (seek() で) オフセットとして使用しますか?

これをコーディングする方法が思い浮かびません >.<

4

8 に答える 8

15

クラス のseekおよびtellメソッドのおかげで、ファイル内の位置を管理できますhttps://docs.python.org/2/tutorial/inputoutput.htmlを参照してくださいfile

このtellメソッドは、次に開いたときに検索する場所を教えてくれます

于 2010-07-21T12:38:33.207 に答える
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()

もちろん、そのように使用するべきではありません。操作をsave_position(myfile)load_position(myfile)のような関数でラップする必要がありますが、機能はすべてそこにあります。

于 2010-07-21T12:44:54.533 に答える
1

ログファイルがメモリに簡単に収まる場合(つまり、適切なローテーション ポリシーがある場合)、次のようなことを簡単に行うことができます。

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)

これを行うことができない場合は、次のようなものを使用できます (受け入れられた回答のシークとテルの使用を参照してください)

于 2010-07-21T12:38:31.293 に答える
0

これがあなたの長さの暗示とtellmethondを使って証明するコードです:

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()
于 2010-07-21T12:59:16.210 に答える
0

これは、読み取ったオフセットを並列ファイルに保存するための効率的で安全なスニペットです。基本的にPythonのlogtail。

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()))
于 2012-02-24T10:53:04.347 に答える
0

ファイルの最後から Python で seek() できることに注意してください。

f.seek(-3, os.SEEK_END)

読み取り位置を EOF から 3 行に置きます。

ただし、シェルまたはdifflibから diff を使用しないのはなぜですか?

于 2010-07-21T12:45:23.833 に答える
0

簡単ですがお勧めしません:):

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)
于 2010-07-21T12:41:47.363 に答える
0

ログ行を行ごとに解析している場合は、最後の解析から行番号を保存できます。次回は良い行から読み始める必要があります。

ファイル内の非常に特定の場所にいる必要がある場合、シークはより便利です。

于 2010-07-21T12:40:28.020 に答える