試み#2:
人々は私がやろうとしていることを理解していないようです。私がそれをより明確に述べることができるかどうか見てみましょう:
1)ファイルのリストを読み取ることは、ディレクトリを歩くよりもはるかに高速です。
2)では、ディレクトリをウォークし、結果のリストをファイルに書き込む関数を作成しましょう。さて、将来、そのディレクトリ内のすべてのファイルを取得したい場合は、ディレクトリを歩く代わりに、このファイルを読み取ることができます。このファイルをインデックスと呼びます。
3)明らかに、ファイルシステムが変更されると、インデックスファイルは同期しなくなります。これを克服するために、ファイルシステムへの変更を監視するためにOSにフックする別のプログラムがあります。それらの変更をモニターログと呼ばれるファイルに書き込みます。特定のディレクトリのインデックスファイルを読み取った直後に、監視ログを使用してさまざまな変更をインデックスに適用し、ディレクトリの現在の状態を反映させます。
ファイルの読み取りはディレクトリを歩くよりもはるかに安価であるため、これは最初の呼び出し以降のすべての呼び出しを歩くよりもはるかに高速であるはずです。
元の投稿:
任意のディレクトリ内のすべてのファイルを再帰的に取得し、さまざまなパラメータに従ってそれらをフィルタリングする関数が必要です。そして、私はそれを速くしたいのです。たとえば、単にdirを歩くよりも1桁速くなります。そして私はPythonでそれをしたいと思います。クロスプラットフォームが望ましいですが、Windowsが最も重要です。
これについての私の考えは次のとおりです。
all_filesという関数があります。
def all_files(dir_path, ...parms...):
...
この関数を初めて呼び出すと、os.walkを使用して、すべてのファイルのリストが、非表示かどうか、シンボリックリンクなどのファイルに関する情報とともに作成されます。このデータをファイルに書き込みます。ディレクトリ内の「.index」と呼ばれます。以降のall_filesの呼び出しで、.indexファイルが検出され、dirをウォークするのではなく、そのファイルを読み取ります。
これにより、ファイルが追加および削除されるときにインデックスが同期しなくなるという問題が残ります。そのために、起動時に実行され、ファイルシステム全体に対するすべての変更を検出し、それらを「mod_log.txt」というファイルに書き込む2番目のプログラムがあります。ここで説明する方法のように、Windows信号を介して変更を検出します。このファイルには、行ごとに1つのイベントが含まれ、各イベントは、影響を受けるパス、イベントのタイプ(作成、削除など)、およびタイムスタンプで構成されます。.indexファイルには、最後に更新された時刻のタイムスタンプも含まれます。all_filesの.indexファイルを読み取った後、mod_log.txtをテールし、タイムスタンプの後に発生したイベントを.indexファイルで見つけます。これらの最近のイベントを取得し、現在のディレクトリに適用されるイベントを見つけて、それに応じて.indexを更新します。
最後に、すべてのファイルのリストを取得し、さまざまなパラメーターに従ってフィルター処理して、結果を返します。
私のアプローチについてどう思いますか?これを行うためのより良い方法はありますか?
編集:
このコードをチェックしてください。再帰的なウォークでキャッシュされたリストを読み取ることで、大幅なスピードアップが見られます。
import os
from os.path import join, exists
import cProfile, pstats
dir_name = "temp_dir"
index_path = ".index"
def create_test_files():
os.mkdir(dir_name)
index_file = open(index_path, 'w')
for i in range(10):
print "creating dir: ", i
sub_dir = join(dir_name, str(i))
os.mkdir(sub_dir)
for i in range(100):
file_path = join(sub_dir, str(i))
open(file_path, 'w').close()
index_file.write(file_path + "\n")
index_file.close()
#
# 0.238 seconds
def test_walk():
for info in os.walk("temp_dir"):
pass
# 0.001 seconds
def test_read():
open(index_path).readlines()
if not exists("temp_dir"):
create_test_files()
def profile(s):
cProfile.run(s, 'profile_results.txt')
p = pstats.Stats('profile_results.txt')
p.strip_dirs().sort_stats('cumulative').print_stats(10)
profile("test_walk()")
profile("test_read()")