asyncio doc: add examples showing the 3 ways to wait for data from an open

socket
This commit is contained in:
Victor Stinner 2014-10-11 16:16:27 +02:00
parent 6888b96cee
commit 04e6df330d
3 changed files with 168 additions and 10 deletions

View File

@ -339,6 +339,10 @@ On Windows with :class:`ProactorEventLoop`, these methods are not supported.
Stop watching the file descriptor for write availability. Stop watching the file descriptor for write availability.
The :ref:`watch a file descriptor for read events <asyncio-watch-read-event>`
example uses the low-level :meth:`BaseEventLoop.add_reader` method to register
the file descriptor of a socket.
Low-level socket operations Low-level socket operations
--------------------------- ---------------------------
@ -663,10 +667,59 @@ Print ``"Hello World"`` every two seconds using a callback scheduled by the
uses a :ref:`coroutine <coroutine>`. uses a :ref:`coroutine <coroutine>`.
Example: Set signal handlers for SIGINT and SIGTERM .. _asyncio-watch-read-event:
---------------------------------------------------
Register handlers for signals :py:data:`SIGINT` and :py:data:`SIGTERM`:: Watch a file descriptor for read events
---------------------------------------
Wait until a file descriptor received some data using the
:meth:`BaseEventLoop.add_reader` method and then close the event loop::
import asyncio
import socket
# Create a pair of connected file descriptors
rsock, wsock = socket.socketpair()
loop = asyncio.get_event_loop()
def reader():
data = rsock.recv(100)
print("Received:", data.decode())
# We are done: unregister the register
loop.remove_reader(rsock)
# Stop the event loop
loop.stop()
# Wait for read event
loop.add_reader(rsock, reader)
# Simulate the reception of data from the network
loop.call_soon(wsock.send, 'abc'.encode())
# Run the event loop
loop.run_forever()
# We are done, close sockets and the event loop
rsock.close()
wsock.close()
loop.close()
.. seealso::
The :ref:`register an open socket to wait for data using a protocol
<asyncio-register-socket>` example uses a low-level protocol created by the
:meth:`BaseEventLoop.create_connection` method.
The :ref:`register an open socket to wait for data using streams
<asyncio-register-socket-streams>` example uses high-level streams
created by the :func:`open_connection` function in a coroutine.
Set signal handlers for SIGINT and SIGTERM
------------------------------------------
Register handlers for signals :py:data:`SIGINT` and :py:data:`SIGTERM` using
the :meth:`BaseEventLoop.add_signal_handler` method::
import asyncio import asyncio
import functools import functools
@ -688,4 +741,3 @@ Register handlers for signals :py:data:`SIGINT` and :py:data:`SIGTERM`::
loop.run_forever() loop.run_forever()
finally: finally:
loop.close() loop.close()

View File

@ -436,11 +436,11 @@ coroutine with ``yield from``. For example, the :meth:`StreamWriter.drain`
coroutine can be used to wait until the write buffer is flushed. coroutine can be used to wait until the write buffer is flushed.
Protocol example: TCP echo server and client Protocol examples
============================================ =================
Echo client TCP echo client
----------- ---------------
TCP echo client example, send data and wait until the connection is closed:: TCP echo client example, send data and wait until the connection is closed::
@ -473,8 +473,8 @@ having to write a short coroutine to handle the exception and stop the
running loop. At :meth:`~BaseEventLoop.run_until_complete` exit, the loop is running loop. At :meth:`~BaseEventLoop.run_until_complete` exit, the loop is
no longer running, so there is no need to stop the loop in case of an error. no longer running, so there is no need to stop the loop in case of an error.
Echo server TCP echo server
----------- ---------------
TCP echo server example, send back received data and close the connection:: TCP echo server example, send back received data and close the connection::
@ -511,4 +511,60 @@ TCP echo server example, send back received data and close the connection::
methods are asynchronous. ``yield from`` is not needed because these transport methods are asynchronous. ``yield from`` is not needed because these transport
methods are not coroutines. methods are not coroutines.
.. _asyncio-register-socket:
Register an open socket to wait for data using a protocol
---------------------------------------------------------
Wait until a socket receives data using the
:meth:`BaseEventLoop.create_connection` method with a protocol, and then close
the event loop ::
import asyncio
import socket
# Create a pair of connected sockets
rsock, wsock = socket.socketpair()
loop = asyncio.get_event_loop()
class MyProtocol(asyncio.Protocol):
transport = None
def connection_made(self, transport):
self.transport = transport
def data_received(self, data):
print("Received:", data.decode())
# We are done: close the transport (it will call connection_lost())
self.transport.close()
def connection_lost(self, exc):
# The socket has been closed, stop the event loop
loop.stop()
# Register the socket to wait for data
connect_coro = loop.create_connection(MyProtocol, sock=rsock)
transport, protocol = loop.run_until_complete(connect_coro)
# Simulate the reception of data from the network
loop.call_soon(wsock.send, 'abc'.encode())
# Run the event loop
loop.run_forever()
# We are done, close sockets and the event loop
rsock.close()
wsock.close()
loop.close()
.. seealso::
The :ref:`watch a file descriptor for read events
<asyncio-watch-read-event>` example uses the low-level
:meth:`BaseEventLoop.add_reader` method to register the file descriptor of a
socket.
The :ref:`register an open socket to wait for data using streams
<asyncio-register-socket-streams>` example uses high-level streams
created by the :func:`open_connection` function in a coroutine.

View File

@ -283,3 +283,53 @@ Usage::
python example.py http://example.com/path/page.html python example.py http://example.com/path/page.html
or with HTTPS::
python example.py https://example.com/path/page.html
.. _asyncio-register-socket-streams:
Register an open socket to wait for data using streams
------------------------------------------------------
Coroutine waiting until a socket receives data using the
:func:`open_connection` function::
import asyncio
import socket
def wait_for_data(loop):
# Create a pair of connected sockets
rsock, wsock = socket.socketpair()
# Register the open socket to wait for data
reader, writer = yield from asyncio.open_connection(sock=rsock, loop=loop)
# Simulate the reception of data from the network
loop.call_soon(wsock.send, 'abc'.encode())
# Wait for data
data = yield from reader.read(100)
# Got data, we are done: close the socket
print("Received:", data.decode())
writer.close()
# Close the second socket
wsock.close()
loop = asyncio.get_event_loop()
loop.run_until_complete(wait_for_data(loop))
loop.close()
.. seealso::
The :ref:`register an open socket to wait for data using a protocol
<asyncio-register-socket>` example uses a low-level protocol created by the
:meth:`BaseEventLoop.create_connection` method.
The :ref:`watch a file descriptor for read events
<asyncio-watch-read-event>` example uses the low-level
:meth:`BaseEventLoop.add_reader` method to register the file descriptor of a
socket.