What, if anything, do I need to do to close a file descriptor I got from
fd = os.open(os.path.expanduser("~/Desktop/foo"), os.O_WRONLY)
with os.fdopen(fd, "wt") as file:
os.close(fd) # OSError: [Errno 9] Bad file descriptor
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
The linux manual on
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.
os.fdopen(fd, *args, **kwargs)
Return an open file object connected to the file descriptor
fd. This is an alias of the
open()built-in function and accepts the same arguments. The only difference is that the first argument of
fdopen()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.