Placement of os.fdopen functionality
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? Jp -- http://catandgirl.com/view.cgi?44 -- up 16 days, 16:00, 5 users, load average: 1.13, 0.93, 0.85
Jp Calderone <exarkun@intarweb.us> writes:
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?
Feel free to file a feature request, but I'd predict that it might sit there for some years until it is closed because of no action. OTOH, if you would produce a patch implementing the feature, it might get attention. Regards, Martin
Jp Calderone <exarkun@intarweb.us>:
perhaps os.fdopen would be more logically placed someplace else - Perhaps as a class method of the file type, file.fromfd()?
Not all OSes have the notion of a file descriptor, which is probably why it's in the os module. Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
On Sat, Apr 05, 2003 at 02:35:31PM -0500, Jp Calderone wrote:
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()?
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. 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) 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 Oren
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/)
If I had to do it over again, your suggestion would make sense;
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.
I can think of another reason for making it a class method: so that custom subclasses of file, or other file-like objects, can override it to create objects of the appropriate type. But since it is an os-dependent feature, the implementation of it probably does belong in the os module. So how about providing a file.fromfd() which calls os.fdopen()? Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
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!
Hmmm, I wasn't sure whether fileno() was a required part of stdio, or whether it only existed on unix-like systems. If it really is required, I guess it doesn't have to be in the os module. Greg Ewing, Computer Science Dept, +--------------------------------------+ University of Canterbury, | A citizen of NewZealandCorp, a | Christchurch, New Zealand | wholly-owned subsidiary of USA Inc. | greg@cosc.canterbury.ac.nz +--------------------------------------+
If I had to do it over again, your suggestion would make sense;
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.
I can think of another reason for making it a class method: so that custom subclasses of file, or other file-like objects, can override it to create objects of the appropriate type.
Yeah, this was the gist of Oren's post (if I understood it correctly).
But since it is an os-dependent feature, the implementation of it probably does belong in the os module.
So how about providing a file.fromfd() which calls os.fdopen()?
I've never seen anyone code a file subclass yet, let alone one that needed this. YAGNI? --Guido van Rossum (home page: http://www.python.org/~guido/)
[Greg Ewing]
Hmmm, I wasn't sure whether fileno() was a required part of stdio, or whether it only existed on unix-like systems. If it really is required, I guess it doesn't have to be in the os module.
It's not required by standard C -- standard C has only streams, not file descriptors. Nevertheless, POSIX requires them, and uses of fileno() in Python are unconditional (aren't conditionally compiled depending on config symbols), so they're on every platform Python links on today.
On Thu, Apr 10, 2003 at 08:48:19PM -0400, Guido van Rossum wrote:
[Greg Ewing]
But since it is an os-dependent feature, the implementation of it probably does belong in the os module.
So how about providing a file.fromfd() which calls os.fdopen()?
I've never seen anyone code a file subclass yet, let alone one that needed this. YAGNI?
codecs.EncodedFile seems almost like it should (but it's just a factory function). Other than that I can't think of anything that does or that would benefit from doing so. Jp -- Lowery's Law: If it jams -- force it. If it breaks, it needed replacing anyway. -- up 22 days, 15:01, 3 users, load average: 1.05, 1.11, 1.16
participants (6)
-
Greg Ewing
-
Guido van Rossum
-
Jp Calderone
-
martin@v.loewis.de
-
Oren Tirosh
-
Tim Peters