Reputation: 62869
I'm trying to create and write a file if it does not exist yet, so that it is co-operatively safe from race conditions, and I'm having (probably stupid) problem. First, here's code:
import os
def safewrite(text, filename):
print "Going to open", filename
fd = os.open(filename, os.O_CREAT | os.O_EXCL, 0666) ##### problem line?
print "Going to write after opening fd", fd
os.write(fd, text)
print "Going to close after writing", text
os.close(fd)
print "Going to return after closing"
#test code to verify file writing works otherwise
f = open("foo2.txt", "w")
f.write("foo\n");
f.close()
f = open("foo2.txt", "r")
print "First write contents:", f.read()
f.close()
os.remove("foo2.txt")
#call the problem method
safewrite ("test\n", "foo2.txt")
Then the problem, I get exception:
First write contents: foo
Going to open foo2.txt
Going to write after opening fd 5
Traceback (most recent call last):
File "/home/user/test.py", line 21, in <module>
safewrite ("test\n", "foo2.txt")
File "/home/user/test.py", line 7, in safewrite
os.write(fd, text)
OSError: [Errno 9] Bad file descriptor
Probable problem line is marked in the code above (I mean, what else could it be?), but I can't figure out how to fix it. What is the problem?
Note: above was tested in a Linux VM, with Python 2.7.3. If you try the code and it works for you, please write a comment with your environment.
Alternative code to do the same thing at least as safely is also very welcome.
Upvotes: 2
Views: 5212
Reputation: 14619
You must open the file with a flag such that you can write to it (os.O_WRONLY
).
From open(2)
:
DESCRIPTION
The argument flags must include one of the following access modes: O_RDONLY, O_WRONLY, or O_RDWR. These request opening the file read-only,
write-only, or read/write, respectively.
From write(2)
:
NAME
write - write to a file descriptor
...
ERRORS
EAGAIN The file descriptor fd has been marked non-blocking (O_NONBLOCK) and the write would block.
EBADF fd is not a valid file descriptor or is not open for writing.
Upvotes: 2
Reputation: 4265
Change the line:
fd = os.open(filename, os.O_CREAT | os.O_EXCL, 0666)
to be instead:
fd=os.open(filename, os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0666)
Upvotes: 9