[Python-Dev] Placement of os.fdopen functionality
Guido van Rossum
guido@python.org
Thu, 10 Apr 2003 15:57:30 -0400
> It occurred to me this afternoon (after answering aquestion about creating
> file objects from file descriptors) that perhaps os.fdopen would be more
> logically placed someplace else - of course it could also remain as
> os.fdopen() for whatever deprecation period is warrented.
>
> Perhaps as a class method of the file type, file.fromfd()?
>
> Should I file a feature request for this on sf, or would it be considered
> too much of a mindless twiddle to bother with?
The latter.
If I had to do it over again, your suggestion would make sense; class
methods are a good way to provide alternative constructors, and we're
doing this e.g. for the new datetime class/module.
But having this in the os module, which deals with such low-level file
descriptors, still strikes me as a pretty decent place to put it as
well, and I don't think it's worth the bother of updating
documentation and so on.
The social cost of deprecating a feature is pretty high. In general,
I'm open to fixing design bugs if keeping the buggy design means
forever having to explain a wart to new users, or forever having to
debug bad code written because of a misunderstanding perpetuated by
the buggy design (like int division). But in this case, I see no
compelling reason; explaining how to do this isn't particularly easier
or harder one way or the other.
Responses to other messages in this thread:
[Greg Ewing]
> Not all OSes have the notion of a file descriptor, which is probably
> why it's in the os module.
Perhaps, but note that file objects have a method fileno(), which
returns a file descriptor. Its implementation is not #ifdefed in any
way -- the C stdio library requires fileno() to exist!
Even if fdopen() really did need an #ifdef, it would be just as simple
only to have the file.fdopen() class method when the C library defines
fdopen() as it is to only have os.fdopen() under those conditions.
[Oren Tirosh]
> I don't see much point in moving it around just because the place
> doesn't seem right but the fact that it's a function rather than a
> method means that some things cannot be done in pure Python.
>
> I can create an uninitialized instance of a subclass of 'file' using
> file.__new__(filesubclass) but the only way to open it is by name
> using file.__init__(filesubclassinstance, 'filename'). A file
> subclass cannot be opened from a file descriptor because fdopen
> always returns a new instance of 'file'.
>
> If there was some way to open an uninitialized file object from a
> file descriptor it would be possible, for example, to write a
> version of popen that returns a subclass of file. It could add a
> method for retrieving the exit code of the process, do something
> interesting on __del__, etc.
You have a point, but it's mostly theoretical: anything involving
popen() should be done in C anyway, and this is no problem in C.
> Here are some alternatives of where this could be implemented,
> followed by what a Python implementation of os.fdopen would look
> like:
>
> 1. New form of file.__new__ with more arguments:
>
> def fdopen(fd, mode='r', buffering=-1):
> return file.__new__('(fdopen)', mode, buffering, fd)
This violates the current invariant that __new__ doesn't initialize
the file with a C-level FILE *.
> 2. Optional argument to file.__init__:
>
> def fdopen(fd, mode='r', buffering=-1):
> return file('(fdopen)', mode, buffering, fd)
>
> 3. Instance method (NOT a class method):
>
> def fdopen(fd, mode='r', buffering=-1):
> f = file.__new__()
> f.fdopen(fd, mode, buffering, '(fdopen)')
> return f
Hm, you seem to be implying that it should not be a class method
because it should be possible to first create an uninitialized
instance with __new__ (possibly of a subclass) and then initialize it
separately. Perhaps. But since class methods also work for
subclasses, I'm not sure I see the use case for this distinction.
In any case I think this should wait until a future redesign of the
stdio library, which will probably do some other refactoring (while
staying compatible with the existing API). I've checked in some rough
ideas in nondist/sandbox/sio/.
--Guido van Rossum (home page: http://www.python.org/~guido/)