如何在不覆盖现有文件的情况下用python创建文件

如何在不覆盖现有文件的情况下用python创建文件,python,multithreading,file,Python,Multithreading,File,目前,我有一个循环,试图通过向文件名字符串添加后缀来查找未使用的文件名。一旦找不到文件,它将使用无法打开具有该名称的新文件的名称。问题是,该代码在网站中使用,并且可能会有多次尝试同时执行相同的操作,因此存在竞争条件 如果一个文件是在检查时间和在另一个线程中打开时间之间创建的,如何防止python覆盖现有文件 我可以通过随机化后缀来最小化这种可能性,但是基于路径名的一部分,这种可能性已经最小化了。我想用一个可以告诉你的函数来消除这种可能性,只在这个文件不存在时创建它 我可以使用win32函数来实现

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

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

我可以通过随机化后缀来最小化这种可能性,但是基于路径名的一部分,这种可能性已经最小化了。我想用一个可以告诉你的函数来消除这种可能性,只在这个文件不存在时创建它


我可以使用win32函数来实现这一点,但我希望它能够跨平台工作,因为它最终将托管在linux上。

如果您担心竞态条件,您可以重新命名它

>>> 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
或者,您可以使用名称中的创建文件。这个项目

>>> import uuid
>>> str(uuid.uuid1())
'64362370-93ef-11de-bf06-0023ae0b04b8'
os.O_create
os.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'

编辑:在Python 3.3中,内置的
x
模式意味着“打开以独占方式创建,如果文件已经存在,则失败”。

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


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

如果我必须这样做,我会使用预定义的文件名,并将当前时间/日期附加到文件名中-这样,不管怎样,都可以保证文件名是唯一的。文件名中当前有日期,问题出在负载较重的Web服务器上,很容易在同一秒内有两个请求。使用uuid.uuid1()创建具有全局唯一名称的文件。我编写了一个小型Python包,通过以unicode安全、线程安全和操作系统安全的方式生成顺序文件名来解决此问题。很久以前。。。但也许有人在这里寻找解决方案。我们就此进行了相关的讨论。也许可以通过目录检查我的OS独立锁定,我正在检查它是否存在,我担心上面提到的竞争条件。临时文件没有delete作为参数。但是NamedTemporaryFile(在v2.6中)确实存在,感谢您提供了指向python库这一部分的指针,我不知道它的存在。UUID可能会工作,但对于我真正需要的东西来说似乎有点异国情调。在Linux/python 2.6上,
os.fdopen(..)
抛出一个
OSError
errno
22,用于上面的示例,因为
mode
参数保留为默认值(
'r'
f=os.fdopen(fd,“w”)
但是可以工作。对于本地(非网络化)文件系统(在类UNIX系统上),这可能是一个有效的假设。(当然,如果open()可能在旧版本的NFS、旧版本的Linux或其他操作系统内核上执行,那么还有其他问题:
>>> 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