Currently I have a loop that tries to find an unused filename by adding suffixes to a filename string. Once it fails to find a file, it uses the name that failed to open a
Use os.open() with os.O_CREAT
and os.O_EXCL
to create the file. That will fail if the file already exists:
>>> 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'
Once you've created a new file, use os.fdopen() to turn the handle into a standard Python file object:
>>> 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
Edit: From Python 3.3, the builtin open() has an x
mode that means "open for exclusive creation, failing if the file already exists".
If you have an id
associated with each thread / process that tries to create the file, you could put that id in the suffix somewhere, thereby guaranteeing that no two processes can use the same file name.
This eliminates the race condition between the processes.
If you are concerned about a race condition, you can create a temporary file and then rename it.
>>> 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
Alternatively, you can create the files using a uuid in the name. Stackoverflow item on this.
>>> import uuid
>>> str(uuid.uuid1())
'64362370-93ef-11de-bf06-0023ae0b04b8'