Python 为什么显式调用os.mkdir()时速度较慢?
我一直在做一个项目,它必须创建一个大的目录结构。我的第一个解决方案是保留所有存在的dir的dict,如果遇到一个尚未使用的dir,则使用os.makedirs()创建它和任何缺少的中介。 当我分析这段代码时,我发现大部分时间(132秒中的105秒)都花在调用posix.stat()以确定中间目录不存在上。然而,我正在一个空目录中构建整个结构,所以我已经知道中间目录都不存在 为了充分利用这一点,我编写了一个版本的代码,其中保存了描述目录树结构的内部备忘录,以便在不查询操作系统的情况下确定创建了哪些目录:Python 为什么显式调用os.mkdir()时速度较慢?,python,linux,python-2.7,operating-system,Python,Linux,Python 2.7,Operating System,我一直在做一个项目,它必须创建一个大的目录结构。我的第一个解决方案是保留所有存在的dir的dict,如果遇到一个尚未使用的dir,则使用os.makedirs()创建它和任何缺少的中介。 当我分析这段代码时,我发现大部分时间(132秒中的105秒)都花在调用posix.stat()以确定中间目录不存在上。然而,我正在一个空目录中构建整个结构,所以我已经知道中间目录都不存在 为了充分利用这一点,我编写了一个版本的代码,其中保存了描述目录树结构的内部备忘录,以便在不查询操作系统的情况下确定创建了哪些
class DirTree:
def __init__(self, root):
self.root = os.path.abspath(root)
self.tree = {}
def makedirs(self, path):
relpath = os.path.relpath(path, self.root).replace('\\', '/')
built = self.root
node = self.tree
for directory in relpath.split('/'):
built = os.path.join(built, directory)
if directory in node:
node = node[directory]
else:
node[directory] = {}
node = node[directory]
os.mkdir(built, 0777)
这段代码确实运行得更快,但是当我通过探查器运行它时,对os.mkdir()的相同4068调用现在需要4倍的时间(94秒而不是24秒)。它不理解为什么从my函数调用此函数比由os.makedirs()调用此函数花费的时间更长。
有人知道为什么吗?os.mkdirs在创建目录之前检查路径组件的存在是正确的。您的代码和os.mkdir都使用c-python模块来实际实现mkdir,在linux上解析为系统调用mkdir 看起来os.mkdir真的不需要统计,因为统计非常耗时,因为如果“a”不存在,那么“a/b”肯定也不存在 使用它可以看出,两种实现调用mkdir的次数相同,但是当路径是相对路径时,您创建的函数无论如何都会构造绝对路径,而os.mkdirs使用相对路径 一种可能性是,额外的时间是操作系统在目录结构中搜索以找到正确的目录,而不是每次都添加到“” os.mkdirs
stat("a/b/c", 0x7fff34b1c4d0) = -1 ENOENT (No such file or directory)
stat("a/b", 0x7fff34b1c260) = -1 ENOENT (No such file or directory)
stat("a", 0x7fff34b1bff0) = -1 ENOENT (No such file or directory)
mkdir("a", 0777) = 0
mkdir("a/b", 0777) = 0
mkdir("a/b/c", 0777) = 0
mkdir("a/b/c/d", 0777) = 0
4003 0.132 0.000 0.132 0.000 {posix.mkdir}
改进的mkdirs
mkdir("/tmp/a", 0777) = 0
mkdir("/tmp/a/b", 0777) = 0
mkdir("/tmp/a/b/c", 0777) = 0
mkdir("/tmp/a/b/c/d", 0777) = 0
4003 0.147 0.000 0.147 0.000 {posix.mkdir}
尽管如此,我无法复制你的结果。我发现os.mkdirs或您的源代码调用mkdir(使用cProfile)所花费的时间大致相同
os.mkdirs
stat("a/b/c", 0x7fff34b1c4d0) = -1 ENOENT (No such file or directory)
stat("a/b", 0x7fff34b1c260) = -1 ENOENT (No such file or directory)
stat("a", 0x7fff34b1bff0) = -1 ENOENT (No such file or directory)
mkdir("a", 0777) = 0
mkdir("a/b", 0777) = 0
mkdir("a/b/c", 0777) = 0
mkdir("a/b/c/d", 0777) = 0
4003 0.132 0.000 0.132 0.000 {posix.mkdir}
改进的mkdirs
mkdir("/tmp/a", 0777) = 0
mkdir("/tmp/a/b", 0777) = 0
mkdir("/tmp/a/b/c", 0777) = 0
mkdir("/tmp/a/b/c/d", 0777) = 0
4003 0.147 0.000 0.147 0.000 {posix.mkdir}
但是,在posixpath中的新源代码中花费了大量时间
4000 0.104 0.000 1.003 0.000 posixpath.py:400(relpath)
也许这是一个人工制品的方法,以概况或微妙的安装。我不认为这是在C端。如果head和tail而不是path.exists(head):在
makedirs()
中执行stat()
调用,则它似乎是。