3

Python で特定のディレクトリのすべての孫を取得しようとしています。パフォーマンス上の理由から、ループ内で OS 関数を呼び出し続けたくありません (これはネットワーク ファイルシステムです)。これは私が現時点で持っているものです。これを行う簡単な方法はありますか?

dirTree = os.walk(root)
children = [os.path.join(root, x) for x in dirTree.next()[1]]
grandChildren = []
for root, dirs, files in dirTree:
    if root in children:
        for dir in dirs:
            grandChildren.append(os.path.join(root, dir))

編集: os.walk への呼び出しが遅延しているかどうかはわかりません。私の意図は、呼び出し後にツリー全体がメモリにあるはずですが、それについてはわかりません。

4

2 に答える 2

5

あなたの質問が正しければ。

ワイルドカード表記を指定することで、glob を使用してファイルまたはディレクトリを取得できます。たとえば、リスト内の「/home/」内のすべてのディレクトリを取得するには、実行できます。

glob.glob('/home/*/*/')

または、すべてのファイルを知ることもできます

glob.glob('/home/*/*')
于 2013-03-06T20:17:42.933 に答える
1

POSIX でも Windows でも、1 回の OS 呼び出しですべてのデータを取得することはできません。少なくとも、POSIX の場合、ディレクトリごとに 3 つ ( opendirreaddirclose)、さらにディレクトリ エントリごとに 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.walks を関数に因数分解します。

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
于 2013-03-06T20:13:18.870 に答える