diff -r a1a936a3b2f6 Doc/library/selectors.rst --- a/Doc/library/selectors.rst Fri Nov 29 18:57:47 2013 +0100 +++ b/Doc/library/selectors.rst Fri Nov 29 21:38:52 2013 +0100 @@ -210,33 +210,80 @@ :func:`select.kqueue` object. -Examples of selector usage:: +Examples +-------- - >>> import selectors - >>> import socket - >>> - >>> s = selectors.DefaultSelector() - >>> r, w = socket.socketpair() - >>> - >>> r.setblocking(False) - >>> w.setblocking(False) - >>> - >>> s.register(r, selectors.EVENT_READ) - SelectorKey(fileobj=, fd=4, events=1, data=None) - >>> s.register(w, selectors.EVENT_WRITE) - SelectorKey(fileobj=, fd=5, events=2, data=None) - >>> - >>> print(s.select()) - [(SelectorKey(fileobj=, fd=5, events=2, data=None), 2)] - >>> - >>> for key, events in s.select(): - ... if events & selectors.EVENT_WRITE: - ... key.fileobj.send(b'spam') - ... - 4 - >>> for key, events in s.select(): - ... if events & selectors.EVENT_READ: - ... print(key.fileobj.recv(1024)) - ... - b'spam' - >>> s.close() +A simple example involving a pair of connected sockets:: + + import selectors + import socket + + + with selectors.DefaultSelector() as selector: + # a pair of connected sockets + r, w = socket.socketpair() + r.setblocking(False) + w.setblocking(False) + + # register both peers + selector.register(r, selectors.EVENT_READ) + selector.register(w, selectors.EVENT_WRITE) + + # at this point, only the write-end should be ready + for key, events in selector.select(): + if events & selectors.EVENT_WRITE: + key.fileobj.send(b'spam') + + # the read-end should now be ready + for key, events in selector.select(): + if events & selectors.EVENT_READ: + print(key.fileobj.recv(1024)) + + +Below is a more complete example, involving multiple readers and writers, and +demonstrating the use of :meth:`BaseSelector.get_map` and +:attr:`SelectorKey.data`:: + + import selectors + import socket + + + with selectors.DefaultSelector() as selector: + + for i in range(10): + # a pair of connected sockets + r, w = socket.socketpair() + r.setblocking(False) + w.setblocking(False) + + # the data to transfer between peers + data = "hello from {}".format(i).encode('ascii') + + # the data to send is passed as opaque `data` parameter when + # registering the writer + selector.register(w, selectors.EVENT_WRITE, bytearray(data)) + # a bytearray used to collect the received data is passed as opaque + # `data` parameter when registering the reader + selector.register(r, selectors.EVENT_READ, bytearray()) + + # keep waiting until all the data has been exchanged between peers + while selector.get_map(): + for key, events in selector.select(): + if events & selectors.EVENT_WRITE: + # a writer is ready: send its data + n = key.fileobj.send(key.data) + del key.data[:n] + if not key.data: + # this writer has sent all its data, it's done + selector.unregister(key.fileobj) + key.fileobj.close() + elif events & selectors.EVENT_READ: + # a reader is ready: receive some data + chunk = key.fileobj.recv(1024) + if chunk: + key.data.extend(chunk) + else: + # EOF, this reader is done + selector.unregister(key.fileobj) + key.fileobj.close() + print("received: {}".format(key.data))