0

私は現在、悲しいことに、あまり一貫して編成されていない多数の散在するxmlファイルに基づいてツリー構造を作成しようとしているプロジェクトにいます。具体的には、特定のファイル拡張子を持つ多数のファイルが与えられた場合に、それらのレイアウトを指示する xml ドキュメントを見つけられるようにしたいということです。幸いなことに、ドキュメントは常に同じ名前になっていますが、残念なことに、リンクしようとしているメディア ファイルに対して常に同じ場所にあるとは限りません。私が見つけた最も賢明な回避策は、ディレクトリ構造内で類似した名前を持つ最も近いファイルを探すことです。ただし、Python でこれを行うことができた唯一の方法は、ディレクトリを調べて、os.walk を使用して検討中のファイルを探すことです。悲しいことに、これはかなり遅いので、多数のメディア ファイルに対してこれを実行できるようにしたいので、より洗練されたソリューションを探しています。以下は、私の現在のアプローチを示すコード例です。

from os import listdir
from os.path import isfile, join, realpath

current_directory = "/path/to/example.mp3"
all_files = lambda path: [file for file in listdir(path) if isfile(join(path,file))]

filename = "test.xml"
found = False
while found is False:
    current_directory = current_directory[:current_directory.rfind("/")]
    current_files = all_files(current_directory)
    if filename in current_files:
        return current_files[current_files.index(filename)]

ディレクトリ構造は、上記の方法が一度に 2 つのファイル インスタンスに到達するほど悪くはありませんが、上記の方法はあまり Pythonic ではなく、必要以上に複雑になっているように感じます。何か案は?

4

1 に答える 1

2

os.walkはインテリジェントです: がtopdownの場合True、編集dirnamesしてチェックするサブディレクトリを指定できます。

おそらく一種のステートマシンでそれを使用すると、すぐにコードがきれいになります..またはハッカーは必要listdirありません.allfilesrfind

コードには再帰的なツリー検索がないため、実際には必要ありませんos.walk()。私が正しければ、あなたのコードは現在のディレクトリで正確な名前をチェックし、次に FS までずっとチェックします。

path = os.path.dirname("/path/to/file.mp3")
target = "test.xml"
top = "/"
while True:
    if os.path.isfile(os.path.join(path,target)):
        #found
        break
    if path==top:   #alternative check for root dir: if os.path.dirname(path)==path
        #not found
        break    
    path=os.path.dirname(path)

別の方法は、親ディレクトリを生成するジェネレーターを使用することですが、それは私には複雑すぎるようです。これはおそらくよりpythonicですが:

def walk_up(path,top):
    while True:
        yield path
        if path==top: raise StopIteration
        else: path=os.path.dirname(path)

found = None
for p in walk_up(os.path.dirname("/path/to/file.mp3"),"/"):
   p = os.path.join(p,target)
   if os.path.isfile(p):
      #found
      found = p
      break
else:
    #not found
于 2013-06-17T13:49:46.957 に答える