現在、enumerate()
を使用してテキストファイルの行数をカウントする非常に単純なスクリプトがあります。
i = 0
f = open("C:/Users/guest/Desktop/file.log", "r")
for i, line in enumerate(f):
pass
print i + 1
f.close()
これは、約3,000万行の15GBのログファイルを処理するのに約3分半かかります。これらは毎日のログであり、毎月の分析を行いたいので、これを2分以内に取得できれば素晴らしいと思います。そのため、コードは約15GBの30個のログを処理する必要があります。おそらく1時間半以上です。 、サーバーの時間とメモリの負荷を最小限に抑えたいと考えています。
私も良い近似/推定方法に落ち着きますが、それは約4有効数字の正確さである必要があります...
ありがとうございました!
Ignacioの答え は正しいですが、32ビットプロセスの場合は失敗する可能性があります。
ただし、ファイルをブロックごとに読み取ってから、各ブロックの\n
文字を数えると便利な場合があります。
def blocks(files, size=65536):
while True:
b = files.read(size)
if not b: break
yield b
with open("file", "r") as f:
print sum(bl.count("\n") for bl in blocks(f))
あなたの仕事をします。
ファイルをバイナリとして開かないことに注意してください。そのため、\r\n
は\n
に変換され、カウントの信頼性が高まります。
Python 3の場合、およびより堅牢にするために、すべての種類の文字を含むファイルを読み取る場合:
def blocks(files, size=65536):
while True:
b = files.read(size)
if not b: break
yield b
with open("file", "r",encoding="utf-8",errors='ignore') as f:
print (sum(bl.count("\n") for bl in blocks(f)))
私はそれが少し不公平であることを知っていますが、あなたはこれを行うことができます
int(subprocess.check_output("wc -l C:\\alarm.bat").split()[0])
Windowsを使用している場合は、 Coreutils を確認してください。
高速な1行のソリューションは次のとおりです。
sum(1 for i in open(file_path, 'rb'))
任意のサイズのファイルで動作するはずです。
mmap ファイル、および改行をカウントアップします。
私はglの答えを拡張し、マルチプロセッシングPythonモジュールを使用して彼/彼女のコードを実行してカウントを高速化します:
def blocks(f, cut, size=64*1024): # 65536
start, chunk =cut
iter=0
read_size=int(size)
_break =False
while not _break:
if _break: break
if f.tell()+size>start+chunk:
read_size=int(start+chunk- f.tell() )
_break=True
b = f.read(read_size)
iter +=1
if not b: break
yield b
def get_chunk_line_count(data):
fn, chunk_id, cut = data
start, chunk =cut
cnt =0
last_bl=None
with open(fn, "r") as f:
if 0:
f.seek(start)
bl = f.read(chunk)
cnt= bl.count('\n')
else:
f.seek(start)
for i, bl in enumerate(blocks(f,cut)):
cnt += bl.count('\n')
last_bl=bl
if not last_bl.endswith('\n'):
cnt -=1
return cnt
....
pool = multiprocessing.Pool(processes=pool_size,
initializer=start_process,
)
pool_outputs = pool.map(get_chunk_line_count, inputs)
pool.close() # no more tasks
pool.join()
これにより、カウントパフォーマンスが20倍向上します。 script にラップして、Githubに配置しました。