2012-01-19 7 views
19

私は大規模なハードディスク上のpythonでファイルルックアップを使いこなしています。私はos.walkとglobを見てきました。私は通常、os.walkを使っています。私はそれをもっとうまく見つけて、通常のサイズのディレクトリの方が速いようです。os.walkまたはglobにすばやく

どちらも誰も経験したことがあり、どちらが効率的であると言えるでしょうか?私が言うように、グロブは遅くなるようですが、ワイルドカードなどを使用することができます。散歩と同じように、結果をフィルタリングする必要があります。コアダンプを参照する例を次に示します。

core = re.compile(r"core\.\d*") 
for root, dirs, files in os.walk("/path/to/dir/") 
    for file in files: 
     if core.search(file): 
      path = os.path.join(root,file) 
      print "Deleting: " + path 
      os.remove(path) 

それとも

for file in iglob("/path/to/dir/core.*") 
    print "Deleting: " + file 
    os.remove(file) 
+3

は、私には時期尚早の最適化のような音。ソース(http://hg.python.org/cpython/file/d01208ba482f/Lib/glob.pyおよびhttp://hg.python.org/cpython/file/d01208ba482f/Lib/os.py)を見てみました。両方の関数が 'os.listdir'と' os.isdir'に依存しているのを見てください。 (しかし、以下の2つの答えで指摘されているように、 'os.walk'はサブディレクトリを再帰し、' glob.iglob'はそうしないので、比較するのは意味がありません)。パフォーマンス上の問題が発生した場合は、いくつかのアプローチを紹介してください。それ以外の場合は、明確なコードを書いてください。 –

答えて

13

となるだろう。タスクは、dirs内のファイルの総数を数えることでした。出力は次のとおりです。

os.listdir: 0.7268s, 1326786 files found 
os.walk: 3.6592s, 1326787 files found 
glob.glob: 2.0133s, 1326786 files found 

ご覧のとおり、os.listdirは最も早いです。このタスクではglog.globはまだos.walkより速いです。

ソース:

import os, time, glob 

n, t = 0, time.time() 
for i in range(1000): 
    n += len(os.listdir("./%d" % i)) 
t = time.time() - t 
print "os.listdir: %.4fs, %d files found" % (t, n) 

n, t = 0, time.time() 
for root, dirs, files in os.walk("./"): 
    for file in files: 
     n += 1 
t = time.time() - t 
print "os.walk: %.4fs, %d files found" % (t, n) 

n, t = 0, time.time() 
for i in range(1000): 
    n += len(glob.glob("./%d/*" % i)) 
t = time.time() - t 
print "glob.glob: %.4fs, %d files found" % (t, n) 
12

あなたは、サブディレクトリを再帰os.walkを使用する必要がある場合。それ以外の場合は、glob.iglobまたはos.listdirを使用する方が簡単だと思います。

+1

+1。特に、ある関数がサブディレクトリを経由して再帰するのに対し、他の関数は再帰しません。 @ aculich。 –

+0

訂正してくれてありがとう。 –

+3

@Steven、globパターン '/ path/to/*/core'は' * 'をワイルドカードとして使います。 'glob'は' * 'を1つのディレクトリに置き換えます。それでも、すべてのサブディレクトリを通して*繰り返されません。 – unutbu

1

os.walkを使用しても、依然としてグロブスタイルマッチングを使用できます。

for root, dirs, files in os.walk(DIRECTORY): 
    for file in files: 
     if glob.fnmatch.fnmatch(file, PATTERN): 
      print file 

ないスピードについて確認が、明らかos.walkが再帰ているので、彼らは別のことを行います。

10

測定/プロファイリングの前に、最適化のための時間を無駄にしないでください。コードをシンプルで保守しやすくすることに重点を置いてください。

例えば、あなたのコードでは、reモジュールにはプリコンパイルされたREの内部re._cacheがあるので、スピードブーストを与えないREをプリコンパイルします。

  1. それは遅いです場合は、いくつかの微調整を行い、最適化し、常にいくつかの最適化がいくつか行われていること、それは

注意を文書化する必要が正確に何を知っていれば、それは簡単な

  • 、その後、
  • をプロファイリングしてください「最適化されていない」コードと比較して、コード実行速度を遅くすることができます。これは、特に現代のJITベースの言語に適用されます。

  • +1

    +1いつ最適化するかについてのアドバイス。 –

    +7

    -1。 OPは「大きなディスク」を言いました。また、コードは既に明らかに単純である。また、OPは最適化の段階にあるようです。 「時期尚早の最適化はblablaの根源」(実際はクヌスの誤った引用)のようなものを使用して、パフォーマンスに関連する質問を破棄することは、SOの疫病です。 – kgadek

    +4

    -1の最適化は、物事がしばしば非常に大規模である実際の(専門的な)世界では重要です。合理的な理由なしに盲目的に最適化を行わないでください – Julius

    0

    *, ?, and character ranges expressed with [] will be correctly matched. This is done by using the os.listdir() and fnmatch.fnmatch() functions

    は、私はあなたのサブディレクトリツリーが直接どのように深く知っている限りでもグロブとあなたはまだ、os.walkに持っていると思います。

    Btw。 glob documentationでそれは言う:

    "*と、文字範囲[]正しく マッチこれは、(os.listdirを使用して行われる)とfnmatch.fnmatch() 機能するだろうと表明?。"

    私は単に私が1000のdirs中のWebページの小さなキャッシュに研究を行った

    for path, subdirs, files in os.walk(path): 
         for name in fnmatch.filter(files, search_str): 
          shutil.copy(os.path.join(path,name), dest) 
    
    関連する問題