【问题标题】:Python "FileExists" error when making directory制作目录时出现Python“FileExists”错误
【发布时间】:2012-09-10 04:28:40
【问题描述】:

我有几个线程在集群系统上从 Python 并行运行。每个 python 线程都输出到一个目录mydir。每个脚本,在输出之前检查 mydir 是否存在,如果不存在则创建它:

if not os.path.isdir(mydir):
    os.makedirs(mydir)

但这会产生错误:

os.makedirs(self.log_dir)                                             
  File "/usr/lib/python2.6/os.py", line 157, in makedirs
mkdir(name,mode)
OSError: [Errno 17] File exists

我怀疑这可能是由于竞争条件造成的,其中一个工作在另一个工作之前创建了 dir。这可能吗?如果是这样,如何避免这个错误?

我不确定这是一个竞争条件,所以想知道 Python 中的其他问题是否会导致这个奇怪的错误。

【问题讨论】:

    标签: python file-io filesystems queue cluster-computing


    【解决方案1】:

    从 Python >=3.2 开始,os.makedirs() 可以采用第三个可选参数 exist_ok

    os.makedirs(mydir, exist_ok=True)
    

    【讨论】:

      【解决方案2】:

      任何时间代码都可以在您检查某事和您对其采取行动之间执行,您将遇到竞争条件。避免这种情况的一种方法(以及 Python 中的常用方法)是尝试然后处理异常

      while True:
          mydir = next_dir_name()
          try:
              os.makedirs(mydir)
              break
          except OSError, e:
              if e.errno != errno.EEXIST:
                  raise   
              # time.sleep might help here
              pass
      

      如果你有很多线程试图创建一系列可预测的目录,这仍然会引发很多异常,但你最终会到达那里。在这种情况下,最好只有一个线程创建目录

      【讨论】:

      • 你为什么在里面有break?该循环只会创建一个目录。
      • Do not 使用硬编码常量!使用 errno.EEXIST 代替幻数 (17)。如果您想更优雅地解决您的问题,请参阅@Jahid answer
      • @patryk.beza,谢谢。对于当今大多数人来说,Jahid 的回答将是更好的方法。
      【解决方案3】:

      捕获异常,如果 errno 为 17,则忽略它。如果在 isdirmakedirs 调用之间存在竞争条件,这是您唯一可以做的事情。

      但是,也有可能存在同名的 文件 - 在这种情况下,os.path.exists 将返回 True,但 os.path.isdir 返回 false。

      【讨论】:

      • 从 Python 3.2 开始使用 exist_ok 参数 os.makedirs 怎么样? (我问是因为从未实际使用过它)。
      • @ovgolovin,看起来可以,但我们还没有多少人能够只支持 3.2 :)
      【解决方案4】:

      我遇到了类似的问题,这就是我所做的

      try:
         if not os.path.exists(os.path.dirname(mydir)):
             os.makedirs(os.path.dirname(mydir))
      except OSError as err:
         print(err)
      

      说明: 仅检查目录是否已存在就会引发此错误消息 [Errno 17] 文件存在 因为我们只是检查 目录名称 是否存在,这将返回正在传递的 mydir 值的目录名称,但如果它已经不存在存在与否。缺少的是不检查该目录是否已经存在,这可以通过使用 os.path.exists() 检查路径来完成,并在那里我们传递了相应的目录名称。

      【讨论】:

      • 我正在创建符号链接,但没有检查它们是否已经创建。重要检查。谢谢你的回答。
      【解决方案5】:

      要忽略目录或文件存在错误,你可以试试这个:

          except OSError, e:
              if e.errno != 17:
                  print("Error:", e)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-09-07
        • 1970-01-01
        • 1970-01-01
        • 2018-05-23
        • 2012-11-11
        • 2012-05-26
        • 1970-01-01
        • 2023-01-12
        相关资源
        最近更新 更多