From ed051594d70fe4c6b170aee667af4e32dfe6b867 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 12 Oct 2014 20:18:16 +0200 Subject: asyncio doc: add TCP echo client/server using streams --- Doc/library/asyncio-protocol.rst | 32 ++++++++++++----- Doc/library/asyncio-stream.rst | 78 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 8 deletions(-) diff --git a/Doc/library/asyncio-protocol.rst b/Doc/library/asyncio-protocol.rst index 487b5ad..2e1218d 100644 --- a/Doc/library/asyncio-protocol.rst +++ b/Doc/library/asyncio-protocol.rst @@ -439,10 +439,13 @@ coroutine can be used to wait until the write buffer is flushed. Protocol examples ================= -TCP echo client ---------------- +.. _asyncio-tcp-echo-client-protocol: -TCP echo client example, send data and wait until the connection is closed:: +TCP echo client protocol +------------------------ + +TCP echo client using the :meth:`BaseEventLoop.create_connection` method, send +data and wait until the connection is closed:: import asyncio @@ -478,11 +481,19 @@ 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 no longer running, so there is no need to stop the loop in case of an error. +.. seealso:: + + The :ref:`TCP echo client using streams ` + example uses the :func:`asyncio.open_connection` function. + -TCP echo server ---------------- +.. _asyncio-tcp-echo-server-protocol: -TCP echo server example, send back received data and close the connection:: +TCP echo server protocol +------------------------ + +TCP echo server using the :meth:`BaseEventLoop.create_server` method, send back +received data and close the connection:: import asyncio @@ -507,12 +518,12 @@ TCP echo server example, send back received data and close the connection:: coro = loop.create_server(EchoServerClientProtocol, '127.0.0.1', 8888) server = loop.run_until_complete(coro) - # Server requests until CTRL+c is pressed + # Serve requests until CTRL+c is pressed print('Serving on {}'.format(server.sockets[0].getsockname())) try: loop.run_forever() except KeyboardInterrupt: - print("exit") + pass # Close the server server.close() @@ -524,6 +535,11 @@ 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 not coroutines. +.. seealso:: + + The :ref:`TCP echo server using streams ` + example uses the :func:`asyncio.start_server` function. + .. _asyncio-udp-echo-client-protocol: diff --git a/Doc/library/asyncio-stream.rst b/Doc/library/asyncio-stream.rst index c3bbd20..1e6dc94 100644 --- a/Doc/library/asyncio-stream.rst +++ b/Doc/library/asyncio-stream.rst @@ -241,6 +241,84 @@ IncompleteReadError Stream examples =============== +.. _asyncio-tcp-echo-client-streams: + +TCP echo client using streams +----------------------------- + +TCP echo client using the :func:`asyncio.open_connection` function:: + + import asyncio + + def tcp_echo_client(message, loop): + reader, writer = yield from asyncio.open_connection('127.0.0.1', 8888, + loop=loop) + + print('Send: %r' % message) + writer.write(message.encode()) + + data = yield from reader.read(100) + print('Received: %r' % data.decode()) + + print('Close the socket') + writer.close() + + message = 'Hello World!' + loop = asyncio.get_event_loop() + loop.run_until_complete(tcp_echo_client(message, loop)) + loop.close() + +.. seealso:: + + The :ref:`TCP echo client protocol ` + example uses the :meth:`BaseEventLoop.create_connection` method. + + +.. _asyncio-tcp-echo-server-streams: + +TCP echo server using streams +----------------------------- + +TCP echo server using the :func:`asyncio.start_server` function:: + + import asyncio + + @asyncio.coroutine + def handle_echo(reader, writer): + data = yield from reader.read(100) + message = data.decode() + addr = writer.get_extra_info('peername') + print("Received %r from %r" % (message, addr)) + + print("Send: %r" % message) + writer.write(data) + yield from writer.drain() + + print("Close the client socket") + writer.close() + + loop = asyncio.get_event_loop() + coro = asyncio.start_server(handle_echo, '127.0.0.1', 8888, loop=loop) + server = loop.run_until_complete(coro) + + # Serve requests until CTRL+c is pressed + print('Serving on {}'.format(server.sockets[0].getsockname())) + try: + loop.run_forever() + except KeyboardInterrupt: + pass + + # Close the server + server.close() + loop.run_until_complete(server.wait_closed()) + loop.close() + +.. seealso:: + + The :ref:`TCP echo server protocol ` + example uses the :meth:`BaseEventLoop.create_server` method. + + Get HTTP headers ---------------- -- cgit v0.12 From 33f6abe4ae7b1fa6d83e26c4dafc0210c09d2254 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 12 Oct 2014 20:36:04 +0200 Subject: asyncio doc: reformat create_server() doc Fix also the reate_unix_connection() doc: the method is not support on Windows, not need to mention that ssl is not support with ProactorEventLoop. --- Doc/library/asyncio-eventloop.rst | 52 ++++++++++++++++++++------------------ Doc/library/asyncio-eventloops.rst | 2 +- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst index 5ffbea7..800fae2 100644 --- a/Doc/library/asyncio-eventloop.rst +++ b/Doc/library/asyncio-eventloop.rst @@ -258,8 +258,6 @@ Creating connections establish the connection in the background. When successful, the coroutine returns a ``(transport, protocol)`` pair. - On Windows with :class:`ProactorEventLoop`, SSL/TLS is not supported. - See the :meth:`BaseEventLoop.create_connection` method for parameters. Availability: UNIX. @@ -270,35 +268,41 @@ Creating listening connections .. method:: BaseEventLoop.create_server(protocol_factory, host=None, port=None, \*, family=socket.AF_UNSPEC, flags=socket.AI_PASSIVE, sock=None, backlog=100, ssl=None, reuse_address=None) - Create a TCP server bound to *host* and *port*. Return a :class:`Server` object, - its :attr:`~Server.sockets` attribute contains created sockets. Use the - :meth:`Server.close` method to stop the server: close listening sockets. + Create a TCP server (socket type :data:`~socket.SOCK_STREAM`) bound to + *host* and *port*. - This method is a :ref:`coroutine `. + Return a :class:`Server` object, its :attr:`~Server.sockets` attribute + contains created sockets. Use the :meth:`Server.close` method to stop the + server: close listening sockets. - If *host* is an empty string or ``None``, all interfaces are assumed - and a list of multiple sockets will be returned (most likely - one for IPv4 and another one for IPv6). + Parameters: - *family* can be set to either :data:`socket.AF_INET` or - :data:`~socket.AF_INET6` to force the socket to use IPv4 or IPv6. If not set - it will be determined from host (defaults to :data:`socket.AF_UNSPEC`). + * If *host* is an empty string or ``None``, all interfaces are assumed + and a list of multiple sockets will be returned (most likely + one for IPv4 and another one for IPv6). - *flags* is a bitmask for :meth:`getaddrinfo`. + * *family* can be set to either :data:`socket.AF_INET` or + :data:`~socket.AF_INET6` to force the socket to use IPv4 or IPv6. If not set + it will be determined from host (defaults to :data:`socket.AF_UNSPEC`). - *sock* can optionally be specified in order to use a preexisting - socket object. + * *flags* is a bitmask for :meth:`getaddrinfo`. - *backlog* is the maximum number of queued connections passed to - :meth:`~socket.socket.listen` (defaults to 100). + * *sock* can optionally be specified in order to use a preexisting + socket object. If specified, *host* and *port* should be omitted (must be + :const:`None`). - *ssl* can be set to an :class:`~ssl.SSLContext` to enable SSL over the - accepted connections. + * *backlog* is the maximum number of queued connections passed to + :meth:`~socket.socket.listen` (defaults to 100). - *reuse_address* tells the kernel to reuse a local socket in - TIME_WAIT state, without waiting for its natural timeout to - expire. If not specified will automatically be set to True on - UNIX. + * *ssl* can be set to an :class:`~ssl.SSLContext` to enable SSL over the + accepted connections. + + * *reuse_address* tells the kernel to reuse a local socket in + TIME_WAIT state, without waiting for its natural timeout to + expire. If not specified will automatically be set to True on + UNIX. + + This method is a :ref:`coroutine `. On Windows with :class:`ProactorEventLoop`, SSL/TLS is not supported. @@ -462,7 +466,7 @@ Use :class:`ProactorEventLoop` to support pipes on Windows. *protocol_factory* should instantiate object with :class:`BaseProtocol` interface. *pipe* is file-like object. - Return pair (transport, protocol), where transport support + Return pair (transport, protocol), where *transport* supports :class:`WriteTransport` interface. With :class:`SelectorEventLoop` event loop, the *pipe* is set to diff --git a/Doc/library/asyncio-eventloops.rst b/Doc/library/asyncio-eventloops.rst index 282cc4b..b871083 100644 --- a/Doc/library/asyncio-eventloops.rst +++ b/Doc/library/asyncio-eventloops.rst @@ -76,7 +76,7 @@ Windows Common limits of Windows event loops: -- :meth:`~BaseEventLoop.create_unix_server` and +- :meth:`~BaseEventLoop.create_unix_connection` and :meth:`~BaseEventLoop.create_unix_server` are not supported: the socket family :data:`socket.AF_UNIX` is specific to UNIX - :meth:`~BaseEventLoop.add_signal_handler` and -- cgit v0.12 From 980dd84f92f689f810ebf10a15f221c8d396ce4e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 12 Oct 2014 21:36:17 +0200 Subject: asyncio doc: more explicit doc for async() The function schedules the execution of coroutines, it's not just a wrapper for something. --- Doc/library/asyncio-task.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst index 8c4d790..fa95ca9 100644 --- a/Doc/library/asyncio-task.rst +++ b/Doc/library/asyncio-task.rst @@ -478,7 +478,8 @@ Task functions .. function:: async(coro_or_future, \*, loop=None) - Wrap a :ref:`coroutine object ` in a future. + Schedule the execution of a :ref:`coroutine object `: wrap it in + a future. Return a :class:`Task` object. If the argument is a :class:`Future`, it is returned directly. -- cgit v0.12 From ab1c85307948219ecf15608b7f7aad41fb8c8670 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 12 Oct 2014 21:37:16 +0200 Subject: asyncio doc: update debug traces --- Doc/library/asyncio-dev.rst | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/Doc/library/asyncio-dev.rst b/Doc/library/asyncio-dev.rst index b797d6a..8ec2ff0 100644 --- a/Doc/library/asyncio-dev.rst +++ b/Doc/library/asyncio-dev.rst @@ -166,26 +166,35 @@ Example of unhandled exception:: Output:: Task exception was never retrieved - future: + future: exception=Exception('not consumed',)> + Traceback (most recent call last): + File "asyncio/tasks.py", line 237, in _step + result = next(coro) + File "asyncio/coroutines.py", line 141, in coro + res = func(*args, **kw) + File "test.py", line 5, in bug + raise Exception("not consumed") + Exception: not consumed + +:ref:`Enable the debug mode of asyncio ` to get the +traceback where the task was created. Output in debug mode:: + + Task exception was never retrieved + future: exception=Exception('not consumed',) created at test.py:8> source_traceback: Object created at (most recent call last): - File "test.py", line 10, in + File "test.py", line 8, in asyncio.async(bug()) - File "asyncio/tasks.py", line 510, in async - task = loop.create_task(coro_or_future) Traceback (most recent call last): - File "asyncio/tasks.py", line 244, in _step + File "asyncio/tasks.py", line 237, in _step result = next(coro) - File "coroutines.py", line 78, in __next__ + File "asyncio/coroutines.py", line 79, in __next__ return next(self.gen) File "asyncio/coroutines.py", line 141, in coro res = func(*args, **kw) - File "test.py", line 7, in bug + File "test.py", line 5, in bug raise Exception("not consumed") Exception: not consumed -:ref:`Enable the debug mode of asyncio ` to get the -traceback where the task was created. - There are different options to fix this issue. The first option is to chain to coroutine in another coroutine and use classic try/except:: @@ -303,15 +312,17 @@ If a pending task is destroyed, the execution of its wrapped :ref:`coroutine Example of log:: Task was destroyed but it is pending! + task: wait_for=> + +:ref:`Enable the debug mode of asyncio ` to get the +traceback where the task was created. Example of log in debug mode:: + + Task was destroyed but it is pending! source_traceback: Object created at (most recent call last): - File "test.py", line 17, in + File "test.py", line 15, in task = asyncio.async(coro, loop=loop) - File "asyncio/tasks.py", line 510, in async - task = loop.create_task(coro_or_future) - task: > + task: wait_for= created at test.py:15> -:ref:`Enable the debug mode of asyncio ` to get the -traceback where the task was created. .. seealso:: -- cgit v0.12