os.listdir()是确定性的吗?

13

根据Python文档,os.listdir() 返回一个包含给定路径下所有目录项名称的列表。该列表是任意排序的。

该列表中项目的排列顺序是任意的。

我想知道的是,这个任意顺序是否总是相同/确定性的?(在不同机器上或者时间上,只要文件夹的内容相同)

编辑:我并没有尝试使其变得确定性,也不想使用它。我只是想知道(例如,它的排序顺序依赖于什么?)


3
为什么?你真的想写依赖于如此微妙特性的代码吗? - Nikola Dimitroff
4
底层操作系统的实现并没有特意将列表随机化。这将取决于具体的实现细节。然而,这仍然是未定义的,不应该完全依赖它。 - deceze
2
您可以按字母顺序对其进行排序,以始终获得确定性行为。 - Gill Bates
4
@NikolaDimitroff,不,我只是好奇并找不到详细的解释。我不是在寻找解决方法或使其确定性的方式(将列表排序确实想到了我)。 - P. Camilleri
我刚刚测试了一件小事情,如果在循环中运行os.listdir100次,则会得到相同的结果。但这仅是具有相同设置的一个会话。 - SuperBiasedMan
4
这很有用:http://znasibov.info/blog/inside_python_understanding_os_listdir.html - Hamish
3个回答

6
为了理解正在发生的事情,我们可以检查Python 3.2的底层实现,该实现可在此处找到:这里
我们将重点关注从2574行开始的POSIX部分。 代码中定义了以下内容:
DIR *dirp;              // will store the pointer to the directory
struct dirent *ep;      // will store the pointer to the entry

有两个重要的POSIX调用: opendir (位于第2596行)和 readdir (位于第2611行)。
正如你从readdir手册页面中读到的那样:

readdir()函数返回指向dirent结构的指针,表示目录流中下一个目录项。 在到达目录流的末尾或发生错误时,它返回NULL。

因此,readdir 读取目录中的下一个条目,但是由文件系统实现定义什么是下一个条目。 您可以在这里阅读更多关于此主题的信息:

[...] 因为这是每个文件系统的事情,所以遍历顺序可以在同一系统上的不同目录中不同,即使它们按相同的顺序创建了相同的条目,这是因为目录使用不同的文件系统类型或仅因为对不同的文件系统设置了一些参数。


5
您可以查看评论中@Hamish发布的链接,它稍微深入了解了Python对UNIX的opendirreaddir实现的钩子函数,您需要进一步了解文件系统以及目录数据结构是如何存储的...然而,简短的版本非常简单:底层文件系统不按文件名排序存储目录项。它关心保持目录项的完整性和一致性,文件名只是与每个目录项关联的任意标签,并且与文件系统的核心功能无关。担心与每个目录项关联的人类可读标签是在更高级别上完成的,例如在您的Python代码中。是的,它是确定性的,当然不是故意随机的。然而,确定性深入到文件系统实现的细节中,文件名的词法顺序在其中不起任何作用。

2
很遗憾,链接已失效。 - Christian Herenz
如果我将一个目录移动到某个地方,然后再移回来,会得到相同的 listdir() 结果吗? - Potemkin
@Potemkin 我不知道,这取决于文件系统的实现细节。正如我在这个答案中所说的:你永远不能期望任何特定的顺序,因为有序的结果(以任何特定的顺序)不是文件系统的设计目标。 - deceze

0

这可能取决于文件系统内部。在典型的Unix机器上,我期望从os.listdir返回值中的项目顺序应该与目录的“dirent”数据结构中的详细信息顺序相同(这又取决于文件系统的具体情况)。

如果添加和删除文件,则不希望目录随时间而具有相同的排序。

除非在从一个到另一个的复制过程中采取了特定的措施,否则我不希望两个“具有相同内容的目录”在两台不同的计算机上具有一致的排序。

根据各种具体情况,单台机器上的排序可能会随着时间的推移而发生变化,而无需对目录进行任何显式更改(尽管我认为我没有看到过实际执行此操作的文件系统,但这绝对是可以完成的操作)。

简而言之,如果您想要任何可推理的排序,请以某种方式对结果进行排序。然后,您就有了保证,即排序将是您的排序所强加的任何内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接