制作目录时出现Python"FileExists"错误

37 python filesystems queue file-io cluster-computing

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

if not os.path.isdir(mydir):
    os.makedirs(mydir)
Run Code Online (Sandbox Code Playgroud)

但这会产生错误:

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

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

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

Jah*_*hid 55

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

os.makedirs(mydir, exist_ok=True)
Run Code Online (Sandbox Code Playgroud)


Joh*_*ooy 46

任何时候代码都可以在您检查某些内容和执行操作之间执行,您将遇到竞争条件.避免这种情况的一种方法(以及Python中的常用方法)是尝试然后处理异常

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

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

  • [**不要**](/sf/ask/3351771/)使用硬编码常量!使用[`errno.EEXIST`](https://docs.python.org/dev/library/errno.html#errno.EEXIST)代替魔术数字(`17`)。如果您想更优雅地解决问题,请参阅[@Jahid答案](/sf/answers/2112248771/)。 (2认同)

Thi*_*ter 16

捕获异常,如果errno为17,则忽略它.如果在isdirmakedirs来电之间存在竞争条件,那么这是唯一可以做的事情.

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

  • 从Python 3.2开始使用`exist_ok`参数[`os.makedirs`](http://docs.python.org/dev/library/os.html?highlight=makedirs#os.makedirs)怎么样?(我问因为从未实际使用过它). (3认同)