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)]

目录结构还不错,上面的方法一次会到达两个文件实例,但我仍然觉得上面的方法不是很pythonic,而且比它真正需要的复杂得多。有任何想法吗?

4

1 回答 1

2

os.walk是智能的:当topdown是时True,您可以编辑dirnames以指定要检查的子目录。

使用它,可能与某种状态机一起使用,将立即使您的代码更整洁——不再需要 .listdirallfileshackery rfind

您的代码中没有递归树搜索,因此确实不需要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 回答