On Jan 2, 9:35 pm, Dave Angel <da...@ieee.org> wrote: > Steven D'Aprano wrote: > > On Sat, 02 Jan 2010 09:40:44 -0800, Aahz wrote: > > >> OTOH, if you want to do something different depending on whether the > >> file exists, you need to use both approaches: > > >> if os.path.exists(fname): > >> try: > >> f = open(fname, 'rb') > >> data = f.read() > >> f.close() > >> return data > >> except IOError: > >> logger.error("Can't read: %s", fname) return '' > >> else: > >> try: > >> f = open(fname, 'wb') > >> f.write(data) > >> f.close() > >> except IOError: > >> logger.error("Can't write: %s", fname) > >> return None > > > Unfortunately, this is still vulnerable to the same sort of race > > condition I spoke about. > > > Even more unfortunately, I don't know that there is any fool-proof way of > > avoiding such race conditions in general. Particularly the problem of > > "open this file for writing only if it doesn't already exist". > > > <snip> > > In Windows, there is a way to do it. It's just not exposed to the > Python built-in function open(). You use the CreateFile() function, > with /dwCreationDisposition/ of CREATE_NEW. > > It's atomic, and fails politely if the file already exists. > > No idea if Unix has a similar functionality.
It does. In Unix, you'd pass O_CREAT|O_EXCL to the open(2) system call (O_CREAT means create a new file, O_EXCL means exclusive mode: fail if the file exists already). The python os.open interface looks suspiciously like the Unix system call as far as invocation goes, but it wraps the Windows functionality properly for the relevant flags. The following should basically work on both OSes (though you'd want to specify a Windows filename, and also set os.O_BINARY or os.O_TEXT as needed on Windows): import os def exclusive_open(fname): rv = os.open(fname, os.O_RDWR|os.O_CREAT|os.O_EXCL) return os.fdopen(rv) first = exclusive_open("/tmp/test") print "SUCCESS: ", first second = exclusive_open("/tmp/test") print "SUCCESS: ", second Run that and you should get: SUCCESS <open file '<fdopen>', mode 'r' at 0xb7f72c38> Traceback (most recent call last): File "testopen.py", line 9, in <module> second = exclusive_open("/tmp/test") File "testopen.py", line 4, in exclusive_open rv = os.open(fname, os.O_RDWR|os.O_CREAT|os.O_EXCL) OSError: [Errno 17] File exists: '/tmp/test' -- http://mail.python.org/mailman/listinfo/python-list