如何在python中创建文件而不覆盖现有文件

时间:2009-08-28 16:14:04

标签: python multithreading

目前我有一个循环试图通过向文件名字符串添加后缀来查找未使用的文件名。一旦找不到文件,它就会使用无法打开具有该名称的新文件的名称。问题是这个代码在网站中使用,并且可能有多次尝试同时执行相同的操作,因此存在竞争条件。

如果在检查时和另一个线程中打开的时间之间创建了一个python,我如何防止python覆盖现有文件。

我可以通过随机化后缀来最小化机会,但是已经根据路径名的部分最小化了机会。我希望通过一个可以被告知的函数来消除这种机会,只有在它不存在的情况下才创建这个文件。

我可以使用win32函数来执行此操作,但我希望这可以跨平台工作,因为它最终会在linux上托管。

3 个答案:

答案 0 :(得分:37)

使用os.open()os.O_CREATos.O_EXCL一起创建文件。如果文件已经存在,那将失败:

>>> fd = os.open("x", os.O_WRONLY | os.O_CREAT | os.O_EXCL)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 17] File exists: 'x'

创建新文件后,使用os.fdopen()将句柄转换为标准Python文件对象:

>>> fd = os.open("y", os.O_WRONLY | os.O_CREAT | os.O_EXCL)
>>> f = os.fdopen(fd, "w")  # f is now a standard Python file object

编辑:从Python 3.3开始,内置open()具有x模式,意味着“打开以进行独占创建,如果文件已存在则失败”。

答案 1 :(得分:7)

如果您担心竞争状况,可以create a temporary file然后重命名。

>>> import os
>>> import tempfile
>>> f = tempfile.NamedTemporaryFile(delete=False)
>>> f.name
'c:\\users\\hughdb~1\\appdata\\local\\temp\\tmpsmdl53'
>>> f.write("Hello world")
>>> f.close()
>>> os.rename(f.name, r'C:\foo.txt')
>>> if os.path.exists(r'C:\foo.txt') :
...     print 'File exists'
...
File exists

或者,您可以使用名称中的uuid创建文件。 Stackoverflow项目。

>>> import uuid
>>> str(uuid.uuid1())
'64362370-93ef-11de-bf06-0023ae0b04b8'

答案 2 :(得分:0)

如果你有一个id与尝试创建文件的每个线程/进程相关联,你可以将该id放在某个地方的后缀中,从而保证没有两个进程可以使用相同的文件名。

这消除了过程之间的竞争条件。