POSIX でも Windows でも、1 回の OS 呼び出しですべてのデータを取得することはできません。少なくとも、POSIX の場合、ディレクトリごとに 3 つ ( opendir
、readdir
、close
)、さらにディレクトリ エントリごとに 1 つ ( stat
) あります。
以下のことにより、投稿したものよりも OS 呼び出しが少なくなると思います。はい、os.walk()
呼び出しは遅延です。つまり、から戻ったときにツリー全体がメモリ内にあるわけwalk()
ではなく、 の呼び出し中に少しずつ読み取られますnext()
。
したがって、私のバージョンは 1 次子孫ディレクトリのみを読み取りstat
、直接の子と孫のみを読み取ります。あなたのバージョンは、ディレクトリ構造と同じくらい深いため、すべてのひ孫に対しても同様に機能します。
root='.'
grandChildren = []
for kid in next(os.walk('.'))[1]:
x = next(os.walk(os.path.join('.', kid)))
for grandKid in x[1]: # (or x[1]+x[2] if you care about regular files)
grandChildren.append(os.path.join(x[0], grandKid))
または、for ループの代わりにリスト内包表記として:
import os
root='.'
grandChildren = [
os.path.join(kid, grandKid)
for kid in next(os.walk(root))[1]
for grandKid in next(os.walk(os.path.join(root, kid)))[1]]
最後に、os.walk
s を関数に因数分解します。
def read_subdirs(dir='.'):
import os
return (os.path.join(dir,x) for x in next(os.walk(dir))[1])
root='.'
grandChildren = [
grandKid
for kid in read_subdirs(root)
for grandKid in read_subdirs(kid)]
stat
テストの結果、ひ孫がいる場合、
私のバージョンはあなたのバージョンよりも呼び出し回数がはるかに少ないことがわかります。
たとえば、私のホーム ディレクトリでは、私のコード ( /tmp/a.py
) とあなたのコード ( /tmp/b.py
)をそれぞれ次のようにroot
設定して実行しました。'.'
$ strace -e stat python /tmp/a.py 2>&1 > /dev/null | egrep -c stat
1245
$ strace -e stat python /tmp/b.py 2>&1 > /dev/null | egrep -c stat
36049