5

ディレクトリを再帰的にウォークしたいのですが、100を超えるファイルがあるディレクトリに遭遇した場合、Pythonが単一のlistdirからブレークするようにします。基本的に、(。TXT)ファイルを検索していますが、DPXイメージシーケンスが大きいディレクトリ(通常は10,000ファイル)は避けたいと思います。DPXはサブディレクトリのないディレクトリに単独で存在するため、そのループをできるだけ早く中断したいと思います。

簡単に言うと、Pythonが「.DPX $」に一致するファイルを検出すると、サブディレクトリの一覧表示を停止し、バックアウトしてそのサブディレクトリをスキップし、他のサブディレクトリのウォークを続行します。

これにより、すべてのリスト結果が返される前にディレクトリリストループを解除できますか?

4

3 に答える 3

4

「ディレクトリリストループ」とは、「os.listdir()いいえ」を意味します。これを破ることはできません。os.path.walk()ただし、またはメソッドを調べて、ファイルos.walk()を含むすべてのディレクトリを削除することもできDPXます。トップダウンで使用os.walk()して歩いている場合は、ディレクトリのリストを変更するだけで、Pythonがどのディレクトリにアクセスするかに影響を与えることができます。os.path.walk()訪問方法で歩く場所を選択できます。

于 2012-05-04T19:05:34.247 に答える
2

のドキュメントによるとos.walk

トップダウンがの場合True、呼び出し元はdirnamesリストをインプレースで変更でき(たとえば、viadelまたはsliceの割り当て)、名前がdirnameswalk()に残っているサブディレクトリにのみ再帰します。これは、検索を整理したり、特定の訪問順序を課したりするために使用できます。トップダウンが有効な ときにdirnameを変更 することは、 dirname自体が生成されるまでに、 dirname内のディレクトリがすでに生成されているため、効果がありません。False

したがって、理論的には、空にした場合dirnamesos.walk追加のディレクトリを再帰的に処理することはありません。「...delまたはsliceの割り当てによる」に関するコメントに注意してください。dirnames=[]これは実際にはdirnamesリストの内容に影響を与えないため、単純に行うことはできません。

于 2012-05-04T19:13:14.240 に答える
1

os.listdirを使用して名前のリストを割り当てないようにする正しい方法は、@CharlesDuffyが言ったようにosレベル関数を使用することです。

この他の投稿からインスピレーションを得て:フォルダ内のファイルをストリームとしてリストし、すぐにプロセスを開始します

特定のOPの質問を解決する方法を追加し、関数のリエントラントバージョンを使用しました。

from ctypes import CDLL, c_char_p, c_int, c_long, c_ushort, c_byte, c_char, Structure, POINTER, byref, cast, sizeof, get_errno
from ctypes.util import find_library

class c_dir(Structure):
    """Opaque type for directory entries, corresponds to struct DIR"""
    pass

class c_dirent(Structure):
    """Directory entry"""
    # FIXME not sure these are the exactly correct types!
    _fields_ = (
        ('d_ino', c_long), # inode number
        ('d_off', c_long), # offset to the next dirent
        ('d_reclen', c_ushort), # length of this record
        ('d_type', c_byte), # type of file; not supported by all file system types
        ('d_name', c_char * 4096) # filename
        )
c_dirent_p = POINTER(c_dirent)
c_dirent_pp = POINTER(c_dirent_p)
c_dir_p = POINTER(c_dir)

c_lib = CDLL(find_library("c"))
opendir = c_lib.opendir
opendir.argtypes = [c_char_p]
opendir.restype = c_dir_p

readdir_r = c_lib.readdir_r
readdir_r.argtypes = [c_dir_p, c_dirent_p, c_dirent_pp]
readdir_r.restype = c_int

closedir = c_lib.closedir
closedir.argtypes = [c_dir_p]
closedir.restype = c_int

import errno

def listdirx(path):
    """
    A generator to return the names of files in the directory passed in
    """
    dir_p = opendir(path)

    if not dir_p:
        raise IOError()

    entry_p = cast(c_lib.malloc(sizeof(c_dirent)), c_dirent_p)

    try:
        while True:
            res = readdir_r(dir_p, entry_p, byref(entry_p))
            if res:
                raise IOError()
            if not entry_p:
                break
            name = entry_p.contents.d_name
            if name not in (".", ".."):
                yield name
    finally:
        if dir_p:
            closedir(dir_p)
        if entry_p:
            c_lib.free(entry_p)

if __name__ == '__main__':
    import sys
    path = sys.argv[1]
    max_per_dir = int(sys.argv[2])
    for idx, entry in enumerate(listdirx(path)):
        if idx >= max_per_dir:
            break
        print entry
于 2012-05-04T22:03:46.750 に答える