2016-08-02 24 views
-1

非常に大きく変化するファイル(通常は約1.5M行)を繰り返し処理し、各行に対して操作を実行しようとしています。これはログファイルなので、ファイルの最後に改行が追加されます。私のプログラムでは、各行が一致しなければならないパラメータを指定し、最新の一致を返すことができます。その結果、ファイルの最後から始めて、プログラムを効率的にするために作業したいと思います(行のリストを作り、それを元に戻すのではなく)。ユーザーは「リンゴ、」I「は、2016年1月4日午後12時りんご」を返すようにライン最も近いたいマッチした1行を要求した場合大容量ファイルを効率的に反復処理する

2016-01-01 01:00 apple 

2016-01-02 05:00 banana 

2016-01-03 03:00 apple 

2016-01-04 00:00 apple 

2016-01-05 12:00 banana 

:ここ

は、例状況ですファイルの末尾に移動します。わずか5行しかない場合でもこれは難しいことではありませんが、何百万人もの人がいるとパフォーマンスが低下します。私は tail -n [file size]を使用してファイルの最後から開始しようとしましたが、この方法はうまく拡張されません。パフォーマンスを向上させるために反復を使用することはできません(結果がファイルの最後の行であれば、私は150万行まで繰り返す必要はありません)。

私が試したもう一つの方法は、「チャンク」にファイルを破壊されています

| 
| Remaining lines 
| 

... 

| 
| Second group of n lines 
| 

| 
| First group of n lines 
| 

私はその後、各チャンクで行だけをストリーミングするためにGNU sedを使用します。しかし、プログラムのパフォーマンスはほとんど向上していないことがわかりました(そして、nが小さくなったときに実際に苦しんでいました)。

これを実行するより良い方法はありますか(ファイルを反復処理しながら実行時間を最小限に抑える)ですか?私はLinuxのコマンドラインから(サブプロセスを通して)他のプログラムを使ってきましたが、Pythonに組み込まれたものを使うのはいいかもしれません。私は正しい方向に私を導く情報を高く評価します。

私はPython 2.7.3,2.7.10,2.7.11-c7,3.3.6、および3.5.1へのアクセス権を持つLinuxを使用しています。

+0

この質問は多くのように、_a lot_を求められます。あなたはまだグーグルでいますか? –

+5

可能なdublicate:http:// stackoverflow。com/questions/3346430 /最も効率的な方法で最初から最後の行になるテキストファイル –

+0

はい、もちろんです。この問題は、表示される行の数を制限しています(つまり、ユーザーが5つの結果を望んでいて、開いている最初の10行に見つかった場合は残りのファイルを読んでいません)。単にファイルを反復処理するだけです( '反転行(open(file).readlines())')私の最善の選択肢ですか? – robben

答えて

0

ファイルを開いた後、ファイルハンドルのseek(bytes, start_point)メソッドを使用して、ファイル内の任意の場所(バイト数)でスキップできます。例:

これは、最初のキロバイトを除き、ファイル内のすべての行を出力します。負の数を指定すると、逆方向に戻り、2番目の引数に2の値を指定すると、ファイルの最後から数えられます。したがって、f.seek(-1024, 2)の呼び出しは上記のファイルの最後のキロバイトのみを出力することになりました。

ファイルがあなたのチャンクサイズよりも小さくなったときにそれが死ぬのを防ぐためのセキュリティ対策が必要な場合がありますが、それは私がやる方法です。 (それはあなたがさらに戻って行く必要があることが判明した場合と、それはまた、非常に些細です:。もう一度seekを呼び出す)

+2

しかし、この警告(この警告)(https://docs.python.org/3/tutorial/inputoutput.html#methods-of-file-objects): "テキストファイルでは、ファイルの先頭からのシークだけが許されます(例外は 'seek(0、2)'で非常にファイルの終わりを探しています)。そして有効なオフセット値は 'f.tell () 'またはゼロです。他のオフセット値は、未定義の動作を生成します。 –

+0

おそらく 'tell 'と' seek'がバイトオフセットを使うからです。任意の値を渡すと、マルチバイト文字の途中で終わる可能性があります。特にこのバグは見つけにくいので、非常に良い点です。 – spectras

0

あなたは使用することができます。

for line in reversed(open("filename").readlines()): 
    print line.rstrip() 

とPython 3:

for line in reversed(list(open("filename"))): 
    print(line.rstrip()) 

これは既にここで回答しています:Read a file in reverse order using python

+0

これは、大きなファイルの場合は非常に遅くなります。 –

関連する問題