One of the problems is that there is a race condition in your previous code, as there is a gap between testing for existence and creating a file. There may be security implications for this (think of someone maliciously inserting a symbolic link into a sensitive file that they cannot overwrite, but your program runs with a higher privilege). Attacks like these are why things like os.tempnam () are deprecated.
To get around this, it is best to try to create the file in such a way as to get an exception if it fails, and if successful, will return an actually open file object. This can be done using the lower level os.open functions by passing the os.O_CREAT and os.O_EXCL flags. After opening, return the actual file (and possibly the name of the file) that you create. For example, here your code has changed to use this approach (returning a tuple (file, file name)):
def unique_file(file_name): counter = 1 file_name_parts = os.path.splitext(file_name)
[Edit] Actually, the best way that will handle the above problems for you is probably to use the tempfile module, although you may lose some naming control. Here is an example of its use (saving a similar interface):
def unique_file(file_name): dirname, filename = os.path.split(file_name) prefix, suffix = os.path.splitext(filename) fd, filename = tempfile.mkstemp(suffix, prefix+"_", dirname) return os.fdopen(fd), filename >>> f, filename=unique_file('/home/some_dir/foo.txt') >>> print filename /home/some_dir/foo_z8f_2Z.txt
The only drawback of this approach is that you always get a file name with some random characters in it, since at first do not try to create an unmodified file (/home/some_dir/foo.txt). You can also look at tempfile.TemporaryFile and NamedTemporaryFile, which will do this, and also automatically delete from disk when closing.
Brian Oct 08 '08 at 16:13 2008-10-08 16:13
source share