【问题标题】:glob.iglob results ordered by name?glob.iglob 结果按名称排序?
【发布时间】:2012-10-31 09:57:22
【问题描述】:

我需要遍历一个可能 非常 大的目录(任意大)。据我了解,常规的 glob.glob 函数将 all 匹配文件名的列表存储在内存中,但 glob.iglob 函数使用迭代器。所以使用常规的glob.glob 函数是不可能的,因为目录中可能有很多个文件。

我的问题是iglob 以看似随机的顺序遍历目录。我希望它按字母顺序遍历文件。我无法一次获得所有文件名的列表,只能对它们进行排序,所以我想知道是否有办法让iglob 按字母顺序遍历目录。

【问题讨论】:

  • A LOT 是多少?现代计算机在内存中保存数百万个文件名应该没有任何问题。

标签: python sorting directory glob


【解决方案1】:

不,没有,没有将目录的所有内容读入内存。操作系统按目录顺序提供文件名,如果要对这些文件进行排序,还需要将内容全部读入内存。

您可以在iglob() 匹配的文件之后对结果进行排序,前提是该集合足够小,可以通过在iglob() 输出上调用sorted() 来放入内存:

for filename in sorted(iglob(path)):

注意iglob() 在不递归到子目录时已经是loads all entries of a single directory into a list(部分原因是fnmatch() returns a list)。

【讨论】:

  • 并在 iglob 上排序将通过将所有内容提取到内存中来耗尽迭代器..
  • @Vadim:如果需要迭代器,您可以随时使用iter(sorted(iglob(path))) 来获得一个(尽管这仍会将所有名称读入内存,因为这是对它们进行排序所必需的)。
【解决方案2】:

来自glob 模块的documentation

glob 模块查找与指定模式匹配的所有路径名 根据 Unix shell 使用的规则。没有波浪号扩展 完成,但*? 和用[] 表示的字符范围将是 正确匹配。 这是通过使用os.listdir()fnmatch.fnmatch() 协同工作,而不是通过实际调用 子壳。

如果我们查看 os.listdir 的文档:

os.listdir(路径)

返回一个列表,其中包含路径给定的目录中条目的名称。 列表顺序随意。它不包括 特殊条目“。”和 '..' 即使它们出现在 目录。

所以glob.glob 不会按字母顺序返回文件。文档中的任何地方都没有说明。依赖这种行为是一个错误。如果你想要一个有序的序列,你必须对结果进行排序。然后你可以很容易地想象到没有办法让iglob 返回一个排序的结果,因为它甚至没有所有可用的结果。

如果内存真的是个问题,那么你有两个选择:

  1. 放弃“aplhabetical order”要求,直接使用iglob
  2. 使用某种“桶排序”对数据进行排序,将大部分数据保留在磁盘上,并将其分块加载到 RAM 中(此类技术在计算机编程艺术第 3 册中进行了说明)。这种方法会使您的程序变慢并且可能更难编写。但是,如果您真的无法将所有文件名保存在 RAM 中,那么您最终将不得不将它们保存在磁盘上。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-25
    • 1970-01-01
    • 2013-12-01
    • 2013-07-21
    • 2018-03-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多