python - 为什么 os.mkdir() 在显式调用时变慢?

标签 python linux python-2.7 operating-system

我一直在从事一个必须创建大型目录结构的项目。我的第一个解决方案是保留所有存在的目录的字典,如果遇到尚未创建的目录,请使用 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 秒)。它不明白为什么这个函数从我的函数调用时比它被 os.makedirs() 调用时花费更长的时间。 有人知道为什么吗?

最佳答案

你是对的,os.mkdirs 在创建目录之前检查路径组件的存在 see here, line 136 .您的代码和 os.mkdirs 都使用了 c-python 模块 posixmodule.c对于 mkdir 的实际实现,它在 Linux 上解析为系统调用 mkdir。

鉴于 stat 非常耗时,看起来 os.mkdir 确实没有必要统计,因为如果“a”不存在,那么肯定“a/b”也不存在。

使用 strace可以看出,两个实现调用 mkdir 的次数相同,但是当路径是相对路径时,您创建的函数无论如何都会构造绝对路径,而 os.mkdirs 使用相对路径。

一个可能性是,额外的时间是操作系统搜索目录结构以找到正确的目录,而不是每次都添加到“。”

操作系统.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

修改后的 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

话虽如此,我无法重现您的结果。我发现 os.mkdirs 或您的源调用 mkdir 所花费的时间(使用 cProfile)大致相同

操作系统.mkdirs

 4003    0.132    0.000    0.132    0.000 {posix.mkdir}

修改后的 mkdirs

 4003    0.147    0.000    0.147    0.000 {posix.mkdir}

但是posixpath中的new source花费了大量的时间

 4000    0.104    0.000    1.003    0.000 posixpath.py:400(relpath)

也许这是分析方法或安装的精妙之处。

关于python - 为什么 os.mkdir() 在显式调用时变慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21442479/

相关文章:

python - Django Admin 嵌套内联

c++ - 向某些屏幕位置写入宽字符时,ncurses 会崩溃

python - 在 Python 2.7.3 中将字段名称分配给 numpy 数组

linux - 遇到 "find:/data/cdr/cdr-ivr.log: No such file or directory"后 Bash 脚本退出

c - linux 管道和缓冲区,不确定如何让循环工作

python - 导入/执行模块并从父模块调用函数

python - 如何在python中从一个列表中创建多个列表

Python _socket.socket vs socket._socketobject,如何从一个转换为另一个

python - 在 python 中创建一个名称中包含变量的列表

python - 尝试使用 BayesSearchCV 调整 MLPClassifier hidden_​​layer_sizes 时出错