[Tutor] sockets, files, threads
Danny Yoo
dyoo at hkn.eecs.berkeley.edu
Wed Jan 19 21:54:16 CET 2005
On Wed, 19 Jan 2005, Marilyn Davis wrote:
> class Exim:
> def __init__(self):
> self.fdin = None
> self.err_flush = []
> self.stdout, self.stdin, self.stderr = popen2.popen3('%s -t' % MAILER)
> self.fdin = self.stdin.fileno()
> self.fdout = self.stdout.fileno()
> self.fderr = self.stderr.fileno()
Hi Marilyn,
You probably don't need to explicitly use the file descriptors here. I see
that you're using them because of the use of select() later on:
###
sel = select.select(self.outlist, [], [], 1)
###
but, although select.select() can use file descriptor numbers, it can also
take file-like objects. See:
http://www.python.org/doc/lib/module-select.html
So you can simplify this code to:
###
sel = select.select([self.stdout, self.stderr], [], [], 1)
###
The upside to this is that you don't need to use the low-level os.read()
or os.close() functions at all.
I suspect that some silliness with file descriptors is causing your bug,
as the following:
###
>>> os.close(42)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
OSError: [Errno 9] Bad file descriptor
###
shows that if we feed os.close() a nonsense file descriptor, it'll throw
out a error message that you may be familiar with.
The error can happen if we close the same file descriptor twice:
###
>>> myin, myout, myerr = popen2.popen3('cat')
>>> os.close(myin.fileno())
>>> os.close(myin.fileno())
Traceback (most recent call last):
File "<stdin>", line 1, in ?
OSError: [Errno 9] Bad file descriptor
###
Here is another particular case that might really be relevant:
###
>>> myin, myout, myerr = popen2.popen3('cat')
>>> os.close(myin.fileno())
>>> myin.close()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
IOError: [Errno 9] Bad file descriptor
###
We're getting an IOError here for exactly the same reasons: the high-level
'myin' object has no knowledge that its underlying file descriptor was
closed.
This is exactly why we've been saying not to mix file-descriptor stuff
with high-level file-like object manipulation: it breaks the assumptions
that the API expects to see.
> However, all that said, I do dimly remember that poplib perhaps had some
> extra processing that maybe is not needed -- but I could be wrong.
Ok; I'll try to remember to look into poplib later and see if there's
anything silly in there.
> if __name__ == '__main__':
> msg = '''To: %s
>
> xx''' % TO_WHOM
>
> p = Exim()
> p.write(msg)
> del p
Instead of using __del__ implicitely, drop the __del__ method and try
calling Exim.close_up() explicitely:
###
p = Exim()
p.write(msg)
p.close_up()
###
> Are you well yet? A lot of sick people around these days!
Feeling better.
More information about the Tutor
mailing list