Overriding 'select'
David Allen
s2mdalle at titan.vcu.edu
Sat Jun 17 23:37:34 EDT 2000
Hello,
I'm relatively new to python, and I've come up with a solution to
one of my problems that is not exactly optimal. I was hoping to
solicit advice on what might be better or 'prettier'.
The problem is this. I've got a Connection object. Each instance
of a Connection object has a field that is a socket. The server
that uses these Connection objects wants to call select() on
Connection objects, not their corresponding sockets. This is
because the Connection object providesa bunch of methods
specific to each connection, and holds a lot of data for the
server.
But when implementing select() inside the Connection object,
I come across the problem - how to use the select() call from
the select module on the socket of the Connection, and then
match it up with the right object later on?
I first wanted to use circular references which didn't work
since sockets seem to be read only. Say I had an instance
foobar with foobar.sock being a socket object. I thought
I could do:
foobar.socket._circular_reference = foobar
so that when the sockets came out the other end of select()
I could just check that field for their corresponding object, but
that didn't work. So I ended up writing this:
(the obj.socket() method returns the socket field from that object)
def select(self, readers, writers, errors, timeout=0):
# Do this with hashes instead of circular pointers.
# make a hash of all the socket objects which hash
# to their corresponding parents
# when select returns, grab the hash values
refhash = {}
reader_sockets = []
writer_sockets = []
errors_sockets = []
for r in readers:
sock = r.socket()
# The socket's value in the dictionary is the
# object the socket belongs to for backreferencing.
refhash[sock] = r
if sock:
reader_sockets.append(sock)
for w in writers:
sock = w.socket()
refhash[sock] = w
if sock:
writer_sockets.append(sock)
for e in errors: sock = e.socket()
refhash[sock] = e
if sock:
errors_sockets.append(sock)
r, w, e = select.select(reader_sockets, writer_sockets,
errors_sockets, 10)
rreturn = []
wreturn = []
ereturn = []
# Find out which object each socket belongs to
for x in r:
rreturn.append(refhash[x])
for x in w:
wreturn.append(refhash[x])
for x in e:
ereturn.append(refhash[x])
return rreturn, wreturn, ereturn
This isn't TOO bad...but it's ugly, and not as fast as
circular references might have been. Creating a
dictionary isn't too bad, but when you have 100 clients,
and this needs to be called a whole lot, it's an unneeded
penalty on CPU and memory to have to create a huge
dictionary every time select gets called (and then destroy
it)
Any ideas on speeding this up, or rewriting in a better
way? Is there any way to get around the read-only problem
on sockets?
--
David Allen
http://opop.nols.com/
----------------------------------------
Have you noticed the way people's intelligence capabilities decline
sharply the minute they start waving guns around?
- Dr. Who
More information about the Python-list
mailing list