72

我有几个线程在集群系统上从 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

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

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

4

5 回答 5

129

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

os.makedirs(mydir, exist_ok=True)
于 2015-05-11T18:25:53.387 回答
56

任何时候代码都可以在您检查某事和您对其采取行动之间执行,您将遇到竞争条件。避免这种情况的一种方法(以及 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

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

于 2012-09-17T22:44:47.473 回答
18

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

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

于 2012-09-17T22:37:56.680 回答
2

I had a similar issues and here is what I did

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

Description: Just checking if the directory already exist throws this error message [Errno 17] File exists because we are just checking if the directory name exist or not which will return the directory name of the mydir value being passed but not if it already exist or not. What is being missed is not checking if that directory already exist which can be done by checking the path with os.path.exists() and in there we passed the respective directory name.

于 2017-07-13T09:45:36.467 回答
0

要忽略目录或文件存在错误,您可以尝试以下操作:

    except OSError, e:
        if e.errno != 17:
            print("Error:", e)
于 2019-11-01T03:11:15.737 回答