如果文件在Python中不存在,则以原子方式创建文件

TLW*_*TLW 5 python atomicity

我正在寻找以下原子版:

import os

def tryMakeFile(filename):
    try:
        with open(filename) as _:
            return False
    except FileNotFoundError:
        with open(filename, mode='a') as _:
            return True
Run Code Online (Sandbox Code Playgroud)

(请不要在这里评论文体问题 - 我知道这个代码在很多方面都很糟糕,但它足以说明我的问题.)

换句话说,我正在寻找一种方法来检查文件是否存在,如果不存在则创建它,在Python中,以我知道发生了哪种方式.但是这样做的方式是在多个进程之间没有竞争条件(在我给出的示例代码中,两个进程都可以认为他们创建了文件,如果第二个进程运行,而第一个进程在第一个和第二个进程之间暂停调用).

或者,换句话说,我正在寻找与Java的Files.createFile调用相当的Python .

编辑:请注意,当我说"Python"时,我的意思是"便携式Python".说"使用这个库*(*这个库只在Windows上可用,或者不在Windows上,或者仅在蓝月亮后的第二个星期二)"并不是我想要的.我正在寻找明确原子的东西,标准库和/或内置的一部分,并且它可以在通用平台上使用.

Pad*_*ham 12

您可以将os.openos.O_CREAT | os.O_EXCL 标志一起使用,如果文件存在则会失败,它们是根据Unix和Windows上可用的文档但是我不确定Windows上是否存在原子文件创建:

os.open("filename", os.O_CREAT | os.O_EXCL)
Run Code Online (Sandbox Code Playgroud)

从linux 打开手册页:

O_EXCL如果设置了O_CREAT和O_EXCL,如果文件存在,open()将失败.检查文件是否存在以及文件的创建(如果不存在)对于执行open()的其他线程来说应该是原子的,在设置了O_EXCL和O_CREAT的同一目录中命名相同的文件名.如果设置了O_EXCL和O_CREAT,并且路径名称为符号链接,则open()将失败并将errno设置为[EEXIST],而不管符号链接的内容如何.如果设置了O_EXCL且未设置O_CREAT,则结果未定义.

如果文件存在,则不确定要执行的操作,但只需要FileExistsError在文件已存在时捕获:

import os

def try_make_file(filename):
    try:
        os.open(filename,  os.O_CREAT | os.O_EXCL)
        return True
    except FileExistsError:
        return False
Run Code Online (Sandbox Code Playgroud)


Eug*_*ash 9

如果你有Python 3.3或更高版本,你可以使用'x'模式open():

'x'打开以进行独占创建,如果文件已存在则失败

def tryMakeFile(filename):
    try:
        with open(filename, "x") as _:
            return False
    except FileExistsError:
        return True
Run Code Online (Sandbox Code Playgroud)

  • 除了重述文档之外,该链接不能解释任何内容. (3认同)
  • @TLW:这似乎是文档的一个缺点。“独占创建”语义确实意味着原子性。另见 http://stackoverflow.com/a/29295749/244297 (2认同)

hre*_*ef_ 5

还有另一种变体,使用pathlib.Path

from pathlib import Path

def try_make_file(filename):
    try:
        Path(filename).touch(exist_ok=False)
        return True
    except FileExistsError:
        return False
Run Code Online (Sandbox Code Playgroud)

它没有明确记录,但在源代码中我们可以看到这暗示了该os.O_EXCL标志:

if not exist_ok:
    flags |= os.O_EXCL
Run Code Online (Sandbox Code Playgroud)

请参阅pathlib 源代码中的函数定义

因此,它具有与其他解决方案相同的属性(即尚不清楚这是否适用于 Windows)。