Reputation: 7408
What, if anything, do I need to do to close a file descriptor I got from os.open
and subsequently used with with os.fdopen
? The OSError
I get from the code below makes me think the answer might be "nothing," but I can't find confirmation in the docs.
fd = os.open(os.path.expanduser("~/Desktop/foo"), os.O_WRONLY)
with os.fdopen(fd, "wt") as file:
pass
os.close(fd) # OSError: [Errno 9] Bad file descriptor
Upvotes: 2
Views: 4620
Reputation: 133879
In Python 2 and normally in Python 3 the file is opened with fdopen
the C standard IO owns the file descriptor. When the file is closed with fclose
then the underlying descriptor is also closed. Thus the file is closed at the end of the with
block.
The linux manual on fdopen
(3) says
The fdopen() function associates a stream with the existing file descriptor, fd. The mode of the stream (one of the values "r", "r+", "w", "w+", "a", "a+") must be compatible with the mode of the file descriptor. The file position indicator of the new stream is set to that belonging to fd, and the error and end-of-file indicators are cleared. Modes "w" or "w+" do not cause truncation of the file. The file descriptor is not dup'ed, and will be closed when the stream created by fdopen() is closed. The result of applying fdopen() to a shared memory object is undefined.
In Python 3 os.fdopen
is a wrapper/almost-alias for the open
builtin function:
os.fdopen(fd, *args, **kwargs)
Return an open file object connected to the file descriptor
fd
. This is an alias of theopen()
built-in function and accepts the same arguments. The only difference is that the first argument offdopen()
must always be an integer.
And the documentation of open
documentation has this to say on opening file descriptors:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
Open file and return a corresponding file object. If the file cannot be opened, an OSError is raised.
file is either a string or bytes object giving the pathname (absolute or relative to the current working directory) of the file to be opened or an integer file descriptor of the file to be wrapped. (If a file descriptor is given, it is closed when the returned I/O object is closed, unless closefd is set to False.)
Thus if you want to keep the file descriptor opened when Python file object is closed, you can do
fd = os.open(os.path.expanduser("~/Desktop/foo"), os.O_WRONLY)
with os.fdopen(fd, "wt", closefd=False) as file:
pass
# I/O object dissociated but fd valid
os.close(fd) # no error.
Upvotes: 7