Python 如何避免与makedirs的竞争条件?

Python 如何避免与makedirs的竞争条件?,python,directory,race-condition,Python,Directory,Race Condition,我正在尝试将以下伪代码转换为Python: If <directory> does not exist: Create all subdirectories for <directory> Create a file in <directory> 然而,经进一步检查,显然存在种族状况。考虑下面的时间线: 指定的目录(/some/path)不存在 Python解释器执行第一行,其计算结果为True 另一个进程创建目录(/some/path) makedi

我正在尝试将以下伪代码转换为Python:

If <directory> does not exist: Create all subdirectories for <directory> Create a file in <directory> 然而,经进一步检查,显然存在种族状况。考虑下面的时间线:

  • 指定的目录(
    /some/path
    )不存在
  • Python解释器执行第一行,其计算结果为
    True
  • 另一个进程创建目录(
    /some/path
  • makedirs
    引发一个
    OSError
    异常,因为目录已经存在
  • 如果目录最初确实存在,但在执行最后一行之前被另一个进程删除,也会出现问题

    说到Python,“请求原谅比获得许可更容易。”记住这一点,上面的片段可以写得更好:

    try:
        os.makedirs('/some/path')
    except OSError:
        pass
    open('/some/path/test.txt', 'w')
    
    这解决了上面描述的两个问题,但创建了第三个问题:
    os.makedirs
    在出现以下情况之一时引发
    OSError
    异常:

    • 该目录已存在
    • 无法创建目录
    这意味着无法确定这两个条件中的哪一个导致引发异常。换句话说,实际的失败将被默默地忽略,这不是我想要的


    如何解决这个问题?

    我会注意到,在Python3中,所有这些都相当合理
    FileExistError
    PermissionError
    是可以捕获的独立异常(
    OSError
    的子类)和
    os。makedirs
    甚至有一个
    exist\u ok
    kwarg,当您对已经存在的目录满意时,可以抑制前者

    如果要检查
    操作错误的原因
    ,则该信息位于
    e.args
    中的元组中(如果只想查看错误代码,还可以选择
    e.errno
    ):

    因此,除了块之外,您必须进行一些内省,并在
    块中以不同的方式处理这两个错误代码。

    好主意!我可以用它代替硬编码
    17
    try:
        os.makedirs('/some/path')
    except OSError:
        pass
    open('/some/path/test.txt', 'w')
    
    try:
        os.makedirs('/etc/python')
    except OSError as e:
        print e.args
    
    (17, 'File exists')
    
    try:
        os.makedirs('/etc/stuff')
    except OSError as e:
        print e.args
    
    (13, 'Permission denied')
    
    try:
        os.makedirs('/etc/stuff')
    except OSError as e:
        print e.errno
    
    13