mirror of https://github.com/python/cpython
1968 lines
65 KiB
ReStructuredText
1968 lines
65 KiB
ReStructuredText
.. currentmodule:: asyncio
|
|
|
|
|
|
.. _asyncio-event-loop:
|
|
|
|
==========
|
|
Event Loop
|
|
==========
|
|
|
|
**Source code:** :source:`Lib/asyncio/events.py`,
|
|
:source:`Lib/asyncio/base_events.py`
|
|
|
|
------------------------------------
|
|
|
|
.. rubric:: Preface
|
|
|
|
The event loop is the core of every asyncio application.
|
|
Event loops run asynchronous tasks and callbacks, perform network
|
|
IO operations, and run subprocesses.
|
|
|
|
Application developers should typically use the high-level asyncio functions,
|
|
such as :func:`asyncio.run`, and should rarely need to reference the loop
|
|
object or call its methods. This section is intended mostly for authors
|
|
of lower-level code, libraries, and frameworks, who need finer control over
|
|
the event loop behavior.
|
|
|
|
.. rubric:: Obtaining the Event Loop
|
|
|
|
The following low-level functions can be used to get, set, or create
|
|
an event loop:
|
|
|
|
.. function:: get_running_loop()
|
|
|
|
Return the running event loop in the current OS thread.
|
|
|
|
Raise a :exc:`RuntimeError` if there is no running event loop.
|
|
|
|
This function can only be called from a coroutine or a callback.
|
|
|
|
.. versionadded:: 3.7
|
|
|
|
.. function:: get_event_loop()
|
|
|
|
Get the current event loop.
|
|
|
|
When called from a coroutine or a callback (e.g. scheduled with
|
|
call_soon or similar API), this function will always return the
|
|
running event loop.
|
|
|
|
If there is no running event loop set, the function will return
|
|
the result of the ``get_event_loop_policy().get_event_loop()`` call.
|
|
|
|
Because this function has rather complex behavior (especially
|
|
when custom event loop policies are in use), using the
|
|
:func:`get_running_loop` function is preferred to :func:`get_event_loop`
|
|
in coroutines and callbacks.
|
|
|
|
As noted above, consider using the higher-level :func:`asyncio.run` function,
|
|
instead of using these lower level functions to manually create and close an
|
|
event loop.
|
|
|
|
.. deprecated:: 3.12
|
|
Deprecation warning is emitted if there is no current event loop.
|
|
In some future Python release this will become an error.
|
|
|
|
.. function:: set_event_loop(loop)
|
|
|
|
Set *loop* as the current event loop for the current OS thread.
|
|
|
|
.. function:: new_event_loop()
|
|
|
|
Create and return a new event loop object.
|
|
|
|
Note that the behaviour of :func:`get_event_loop`, :func:`set_event_loop`,
|
|
and :func:`new_event_loop` functions can be altered by
|
|
:ref:`setting a custom event loop policy <asyncio-policies>`.
|
|
|
|
|
|
.. rubric:: Contents
|
|
|
|
This documentation page contains the following sections:
|
|
|
|
* The `Event Loop Methods`_ section is the reference documentation of
|
|
the event loop APIs;
|
|
|
|
* The `Callback Handles`_ section documents the :class:`Handle` and
|
|
:class:`TimerHandle` instances which are returned from scheduling
|
|
methods such as :meth:`loop.call_soon` and :meth:`loop.call_later`;
|
|
|
|
* The `Server Objects`_ section documents types returned from
|
|
event loop methods like :meth:`loop.create_server`;
|
|
|
|
* The `Event Loop Implementations`_ section documents the
|
|
:class:`SelectorEventLoop` and :class:`ProactorEventLoop` classes;
|
|
|
|
* The `Examples`_ section showcases how to work with some event
|
|
loop APIs.
|
|
|
|
|
|
.. _asyncio-event-loop-methods:
|
|
|
|
Event Loop Methods
|
|
==================
|
|
|
|
Event loops have **low-level** APIs for the following:
|
|
|
|
.. contents::
|
|
:depth: 1
|
|
:local:
|
|
|
|
|
|
Running and stopping the loop
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
.. method:: loop.run_until_complete(future)
|
|
|
|
Run until the *future* (an instance of :class:`Future`) has
|
|
completed.
|
|
|
|
If the argument is a :ref:`coroutine object <coroutine>` it
|
|
is implicitly scheduled to run as a :class:`asyncio.Task`.
|
|
|
|
Return the Future's result or raise its exception.
|
|
|
|
.. method:: loop.run_forever()
|
|
|
|
Run the event loop until :meth:`stop` is called.
|
|
|
|
If :meth:`stop` is called before :meth:`run_forever()` is called,
|
|
the loop will poll the I/O selector once with a timeout of zero,
|
|
run all callbacks scheduled in response to I/O events (and
|
|
those that were already scheduled), and then exit.
|
|
|
|
If :meth:`stop` is called while :meth:`run_forever` is running,
|
|
the loop will run the current batch of callbacks and then exit.
|
|
Note that new callbacks scheduled by callbacks will not run in this
|
|
case; instead, they will run the next time :meth:`run_forever` or
|
|
:meth:`run_until_complete` is called.
|
|
|
|
.. method:: loop.stop()
|
|
|
|
Stop the event loop.
|
|
|
|
.. method:: loop.is_running()
|
|
|
|
Return ``True`` if the event loop is currently running.
|
|
|
|
.. method:: loop.is_closed()
|
|
|
|
Return ``True`` if the event loop was closed.
|
|
|
|
.. method:: loop.close()
|
|
|
|
Close the event loop.
|
|
|
|
The loop must not be running when this function is called.
|
|
Any pending callbacks will be discarded.
|
|
|
|
This method clears all queues and shuts down the executor, but does
|
|
not wait for the executor to finish.
|
|
|
|
This method is idempotent and irreversible. No other methods
|
|
should be called after the event loop is closed.
|
|
|
|
.. coroutinemethod:: loop.shutdown_asyncgens()
|
|
|
|
Schedule all currently open :term:`asynchronous generator` objects to
|
|
close with an :meth:`~agen.aclose()` call. After calling this method,
|
|
the event loop will issue a warning if a new asynchronous generator
|
|
is iterated. This should be used to reliably finalize all scheduled
|
|
asynchronous generators.
|
|
|
|
Note that there is no need to call this function when
|
|
:func:`asyncio.run` is used.
|
|
|
|
Example::
|
|
|
|
try:
|
|
loop.run_forever()
|
|
finally:
|
|
loop.run_until_complete(loop.shutdown_asyncgens())
|
|
loop.close()
|
|
|
|
.. versionadded:: 3.6
|
|
|
|
.. coroutinemethod:: loop.shutdown_default_executor(timeout=None)
|
|
|
|
Schedule the closure of the default executor and wait for it to join all of
|
|
the threads in the :class:`~concurrent.futures.ThreadPoolExecutor`.
|
|
Once this method has been called,
|
|
using the default executor with :meth:`loop.run_in_executor`
|
|
will raise a :exc:`RuntimeError`.
|
|
|
|
The *timeout* parameter specifies the amount of time
|
|
(in :class:`float` seconds) the executor will be given to finish joining.
|
|
With the default, ``None``,
|
|
the executor is allowed an unlimited amount of time.
|
|
|
|
If the *timeout* is reached, a :exc:`RuntimeWarning` is emitted
|
|
and the default executor is terminated
|
|
without waiting for its threads to finish joining.
|
|
|
|
.. note::
|
|
|
|
Do not call this method when using :func:`asyncio.run`,
|
|
as the latter handles default executor shutdown automatically.
|
|
|
|
.. versionadded:: 3.9
|
|
|
|
.. versionchanged:: 3.12
|
|
Added the *timeout* parameter.
|
|
|
|
Scheduling callbacks
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
|
|
.. method:: loop.call_soon(callback, *args, context=None)
|
|
|
|
Schedule the *callback* :term:`callback` to be called with
|
|
*args* arguments at the next iteration of the event loop.
|
|
|
|
Return an instance of :class:`asyncio.Handle`,
|
|
which can be used later to cancel the callback.
|
|
|
|
Callbacks are called in the order in which they are registered.
|
|
Each callback will be called exactly once.
|
|
|
|
The optional keyword-only *context* argument specifies a
|
|
custom :class:`contextvars.Context` for the *callback* to run in.
|
|
Callbacks use the current context when no *context* is provided.
|
|
|
|
Unlike :meth:`call_soon_threadsafe`, this method is not thread-safe.
|
|
|
|
.. method:: loop.call_soon_threadsafe(callback, *args, context=None)
|
|
|
|
A thread-safe variant of :meth:`call_soon`. When scheduling callbacks from
|
|
another thread, this function *must* be used, since :meth:`call_soon` is not
|
|
thread-safe.
|
|
|
|
Raises :exc:`RuntimeError` if called on a loop that's been closed.
|
|
This can happen on a secondary thread when the main application is
|
|
shutting down.
|
|
|
|
See the :ref:`concurrency and multithreading <asyncio-multithreading>`
|
|
section of the documentation.
|
|
|
|
.. versionchanged:: 3.7
|
|
The *context* keyword-only parameter was added. See :pep:`567`
|
|
for more details.
|
|
|
|
.. _asyncio-pass-keywords:
|
|
|
|
.. note::
|
|
|
|
Most :mod:`asyncio` scheduling functions don't allow passing
|
|
keyword arguments. To do that, use :func:`functools.partial`::
|
|
|
|
# will schedule "print("Hello", flush=True)"
|
|
loop.call_soon(
|
|
functools.partial(print, "Hello", flush=True))
|
|
|
|
Using partial objects is usually more convenient than using lambdas,
|
|
as asyncio can render partial objects better in debug and error
|
|
messages.
|
|
|
|
|
|
.. _asyncio-delayed-calls:
|
|
|
|
Scheduling delayed callbacks
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Event loop provides mechanisms to schedule callback functions
|
|
to be called at some point in the future. Event loop uses monotonic
|
|
clocks to track time.
|
|
|
|
|
|
.. method:: loop.call_later(delay, callback, *args, context=None)
|
|
|
|
Schedule *callback* to be called after the given *delay*
|
|
number of seconds (can be either an int or a float).
|
|
|
|
An instance of :class:`asyncio.TimerHandle` is returned which can
|
|
be used to cancel the callback.
|
|
|
|
*callback* will be called exactly once. If two callbacks are
|
|
scheduled for exactly the same time, the order in which they
|
|
are called is undefined.
|
|
|
|
The optional positional *args* will be passed to the callback when
|
|
it is called. If you want the callback to be called with keyword
|
|
arguments use :func:`functools.partial`.
|
|
|
|
An optional keyword-only *context* argument allows specifying a
|
|
custom :class:`contextvars.Context` for the *callback* to run in.
|
|
The current context is used when no *context* is provided.
|
|
|
|
.. versionchanged:: 3.7
|
|
The *context* keyword-only parameter was added. See :pep:`567`
|
|
for more details.
|
|
|
|
.. versionchanged:: 3.8
|
|
In Python 3.7 and earlier with the default event loop implementation,
|
|
the *delay* could not exceed one day.
|
|
This has been fixed in Python 3.8.
|
|
|
|
.. method:: loop.call_at(when, callback, *args, context=None)
|
|
|
|
Schedule *callback* to be called at the given absolute timestamp
|
|
*when* (an int or a float), using the same time reference as
|
|
:meth:`loop.time`.
|
|
|
|
This method's behavior is the same as :meth:`call_later`.
|
|
|
|
An instance of :class:`asyncio.TimerHandle` is returned which can
|
|
be used to cancel the callback.
|
|
|
|
.. versionchanged:: 3.7
|
|
The *context* keyword-only parameter was added. See :pep:`567`
|
|
for more details.
|
|
|
|
.. versionchanged:: 3.8
|
|
In Python 3.7 and earlier with the default event loop implementation,
|
|
the difference between *when* and the current time could not exceed
|
|
one day. This has been fixed in Python 3.8.
|
|
|
|
.. method:: loop.time()
|
|
|
|
Return the current time, as a :class:`float` value, according to
|
|
the event loop's internal monotonic clock.
|
|
|
|
.. note::
|
|
.. versionchanged:: 3.8
|
|
In Python 3.7 and earlier timeouts (relative *delay* or absolute *when*)
|
|
should not exceed one day. This has been fixed in Python 3.8.
|
|
|
|
.. seealso::
|
|
|
|
The :func:`asyncio.sleep` function.
|
|
|
|
|
|
Creating Futures and Tasks
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
.. method:: loop.create_future()
|
|
|
|
Create an :class:`asyncio.Future` object attached to the event loop.
|
|
|
|
This is the preferred way to create Futures in asyncio. This lets
|
|
third-party event loops provide alternative implementations of
|
|
the Future object (with better performance or instrumentation).
|
|
|
|
.. versionadded:: 3.5.2
|
|
|
|
.. method:: loop.create_task(coro, *, name=None, context=None)
|
|
|
|
Schedule the execution of :ref:`coroutine <coroutine>` *coro*.
|
|
Return a :class:`Task` object.
|
|
|
|
Third-party event loops can use their own subclass of :class:`Task`
|
|
for interoperability. In this case, the result type is a subclass
|
|
of :class:`Task`.
|
|
|
|
If the *name* argument is provided and not ``None``, it is set as
|
|
the name of the task using :meth:`Task.set_name`.
|
|
|
|
An optional keyword-only *context* argument allows specifying a
|
|
custom :class:`contextvars.Context` for the *coro* to run in.
|
|
The current context copy is created when no *context* is provided.
|
|
|
|
.. versionchanged:: 3.8
|
|
Added the *name* parameter.
|
|
|
|
.. versionchanged:: 3.11
|
|
Added the *context* parameter.
|
|
|
|
.. method:: loop.set_task_factory(factory)
|
|
|
|
Set a task factory that will be used by
|
|
:meth:`loop.create_task`.
|
|
|
|
If *factory* is ``None`` the default task factory will be set.
|
|
Otherwise, *factory* must be a *callable* with the signature matching
|
|
``(loop, coro, context=None)``, where *loop* is a reference to the active
|
|
event loop, and *coro* is a coroutine object. The callable
|
|
must return a :class:`asyncio.Future`-compatible object.
|
|
|
|
.. method:: loop.get_task_factory()
|
|
|
|
Return a task factory or ``None`` if the default one is in use.
|
|
|
|
|
|
Opening network connections
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
.. coroutinemethod:: loop.create_connection(protocol_factory, \
|
|
host=None, port=None, *, ssl=None, \
|
|
family=0, proto=0, flags=0, sock=None, \
|
|
local_addr=None, server_hostname=None, \
|
|
ssl_handshake_timeout=None, \
|
|
ssl_shutdown_timeout=None, \
|
|
happy_eyeballs_delay=None, interleave=None, \
|
|
all_errors=False)
|
|
|
|
Open a streaming transport connection to a given
|
|
address specified by *host* and *port*.
|
|
|
|
The socket family can be either :py:const:`~socket.AF_INET` or
|
|
:py:const:`~socket.AF_INET6` depending on *host* (or the *family*
|
|
argument, if provided).
|
|
|
|
The socket type will be :py:const:`~socket.SOCK_STREAM`.
|
|
|
|
*protocol_factory* must be a callable returning an
|
|
:ref:`asyncio protocol <asyncio-protocol>` implementation.
|
|
|
|
This method will try to establish the connection in the background.
|
|
When successful, it returns a ``(transport, protocol)`` pair.
|
|
|
|
The chronological synopsis of the underlying operation is as follows:
|
|
|
|
#. The connection is established and a :ref:`transport <asyncio-transport>`
|
|
is created for it.
|
|
|
|
#. *protocol_factory* is called without arguments and is expected to
|
|
return a :ref:`protocol <asyncio-protocol>` instance.
|
|
|
|
#. The protocol instance is coupled with the transport by calling its
|
|
:meth:`~BaseProtocol.connection_made` method.
|
|
|
|
#. A ``(transport, protocol)`` tuple is returned on success.
|
|
|
|
The created transport is an implementation-dependent bidirectional
|
|
stream.
|
|
|
|
Other arguments:
|
|
|
|
* *ssl*: if given and not false, a SSL/TLS transport is created
|
|
(by default a plain TCP transport is created). If *ssl* is
|
|
a :class:`ssl.SSLContext` object, this context is used to create
|
|
the transport; if *ssl* is :const:`True`, a default context returned
|
|
from :func:`ssl.create_default_context` is used.
|
|
|
|
.. seealso:: :ref:`SSL/TLS security considerations <ssl-security>`
|
|
|
|
* *server_hostname* sets or overrides the hostname that the target
|
|
server's certificate will be matched against. Should only be passed
|
|
if *ssl* is not ``None``. By default the value of the *host* argument
|
|
is used. If *host* is empty, there is no default and you must pass a
|
|
value for *server_hostname*. If *server_hostname* is an empty
|
|
string, hostname matching is disabled (which is a serious security
|
|
risk, allowing for potential man-in-the-middle attacks).
|
|
|
|
* *family*, *proto*, *flags* are the optional address family, protocol
|
|
and flags to be passed through to getaddrinfo() for *host* resolution.
|
|
If given, these should all be integers from the corresponding
|
|
:mod:`socket` module constants.
|
|
|
|
* *happy_eyeballs_delay*, if given, enables Happy Eyeballs for this
|
|
connection. It should
|
|
be a floating-point number representing the amount of time in seconds
|
|
to wait for a connection attempt to complete, before starting the next
|
|
attempt in parallel. This is the "Connection Attempt Delay" as defined
|
|
in :rfc:`8305`. A sensible default value recommended by the RFC is ``0.25``
|
|
(250 milliseconds).
|
|
|
|
* *interleave* controls address reordering when a host name resolves to
|
|
multiple IP addresses.
|
|
If ``0`` or unspecified, no reordering is done, and addresses are
|
|
tried in the order returned by :meth:`getaddrinfo`. If a positive integer
|
|
is specified, the addresses are interleaved by address family, and the
|
|
given integer is interpreted as "First Address Family Count" as defined
|
|
in :rfc:`8305`. The default is ``0`` if *happy_eyeballs_delay* is not
|
|
specified, and ``1`` if it is.
|
|
|
|
* *sock*, if given, should be an existing, already connected
|
|
:class:`socket.socket` object to be used by the transport.
|
|
If *sock* is given, none of *host*, *port*, *family*, *proto*, *flags*,
|
|
*happy_eyeballs_delay*, *interleave*
|
|
and *local_addr* should be specified.
|
|
|
|
.. note::
|
|
|
|
The *sock* argument transfers ownership of the socket to the
|
|
transport created. To close the socket, call the transport's
|
|
:meth:`~asyncio.BaseTransport.close` method.
|
|
|
|
* *local_addr*, if given, is a ``(local_host, local_port)`` tuple used
|
|
to bind the socket locally. The *local_host* and *local_port*
|
|
are looked up using ``getaddrinfo()``, similarly to *host* and *port*.
|
|
|
|
* *ssl_handshake_timeout* is (for a TLS connection) the time in seconds
|
|
to wait for the TLS handshake to complete before aborting the connection.
|
|
``60.0`` seconds if ``None`` (default).
|
|
|
|
* *ssl_shutdown_timeout* is the time in seconds to wait for the SSL shutdown
|
|
to complete before aborting the connection. ``30.0`` seconds if ``None``
|
|
(default).
|
|
|
|
* *all_errors* determines what exceptions are raised when a connection cannot
|
|
be created. By default, only a single ``Exception`` is raised: the first
|
|
exception if there is only one or all errors have same message, or a single
|
|
``OSError`` with the error messages combined. When ``all_errors`` is ``True``,
|
|
an ``ExceptionGroup`` will be raised containing all exceptions (even if there
|
|
is only one).
|
|
|
|
|
|
.. versionchanged:: 3.5
|
|
|
|
Added support for SSL/TLS in :class:`ProactorEventLoop`.
|
|
|
|
.. versionchanged:: 3.6
|
|
|
|
The socket option :ref:`socket.TCP_NODELAY <socket-unix-constants>` is set by default
|
|
for all TCP connections.
|
|
|
|
.. versionchanged:: 3.7
|
|
|
|
Added the *ssl_handshake_timeout* parameter.
|
|
|
|
.. versionchanged:: 3.8
|
|
|
|
Added the *happy_eyeballs_delay* and *interleave* parameters.
|
|
|
|
Happy Eyeballs Algorithm: Success with Dual-Stack Hosts.
|
|
When a server's IPv4 path and protocol are working, but the server's
|
|
IPv6 path and protocol are not working, a dual-stack client
|
|
application experiences significant connection delay compared to an
|
|
IPv4-only client. This is undesirable because it causes the
|
|
dual-stack client to have a worse user experience. This document
|
|
specifies requirements for algorithms that reduce this user-visible
|
|
delay and provides an algorithm.
|
|
|
|
For more information: https://datatracker.ietf.org/doc/html/rfc6555
|
|
|
|
.. versionchanged:: 3.11
|
|
|
|
Added the *ssl_shutdown_timeout* parameter.
|
|
|
|
.. versionchanged:: 3.12
|
|
*all_errors* was added.
|
|
|
|
.. seealso::
|
|
|
|
The :func:`open_connection` function is a high-level alternative
|
|
API. It returns a pair of (:class:`StreamReader`, :class:`StreamWriter`)
|
|
that can be used directly in async/await code.
|
|
|
|
.. coroutinemethod:: loop.create_datagram_endpoint(protocol_factory, \
|
|
local_addr=None, remote_addr=None, *, \
|
|
family=0, proto=0, flags=0, \
|
|
reuse_port=None, \
|
|
allow_broadcast=None, sock=None)
|
|
|
|
Create a datagram connection.
|
|
|
|
The socket family can be either :py:const:`~socket.AF_INET`,
|
|
:py:const:`~socket.AF_INET6`, or :py:const:`~socket.AF_UNIX`,
|
|
depending on *host* (or the *family* argument, if provided).
|
|
|
|
The socket type will be :py:const:`~socket.SOCK_DGRAM`.
|
|
|
|
*protocol_factory* must be a callable returning a
|
|
:ref:`protocol <asyncio-protocol>` implementation.
|
|
|
|
A tuple of ``(transport, protocol)`` is returned on success.
|
|
|
|
Other arguments:
|
|
|
|
* *local_addr*, if given, is a ``(local_host, local_port)`` tuple used
|
|
to bind the socket locally. The *local_host* and *local_port*
|
|
are looked up using :meth:`getaddrinfo`.
|
|
|
|
* *remote_addr*, if given, is a ``(remote_host, remote_port)`` tuple used
|
|
to connect the socket to a remote address. The *remote_host* and
|
|
*remote_port* are looked up using :meth:`getaddrinfo`.
|
|
|
|
* *family*, *proto*, *flags* are the optional address family, protocol
|
|
and flags to be passed through to :meth:`getaddrinfo` for *host*
|
|
resolution. If given, these should all be integers from the
|
|
corresponding :mod:`socket` module constants.
|
|
|
|
* *reuse_port* tells the kernel to allow this endpoint to be bound to the
|
|
same port as other existing endpoints are bound to, so long as they all
|
|
set this flag when being created. This option is not supported on Windows
|
|
and some Unixes. If the :ref:`socket.SO_REUSEPORT <socket-unix-constants>` constant is not
|
|
defined then this capability is unsupported.
|
|
|
|
* *allow_broadcast* tells the kernel to allow this endpoint to send
|
|
messages to the broadcast address.
|
|
|
|
* *sock* can optionally be specified in order to use a preexisting,
|
|
already connected, :class:`socket.socket` object to be used by the
|
|
transport. If specified, *local_addr* and *remote_addr* should be omitted
|
|
(must be :const:`None`).
|
|
|
|
.. note::
|
|
|
|
The *sock* argument transfers ownership of the socket to the
|
|
transport created. To close the socket, call the transport's
|
|
:meth:`~asyncio.BaseTransport.close` method.
|
|
|
|
See :ref:`UDP echo client protocol <asyncio-udp-echo-client-protocol>` and
|
|
:ref:`UDP echo server protocol <asyncio-udp-echo-server-protocol>` examples.
|
|
|
|
.. versionchanged:: 3.4.4
|
|
The *family*, *proto*, *flags*, *reuse_address*, *reuse_port*,
|
|
*allow_broadcast*, and *sock* parameters were added.
|
|
|
|
.. versionchanged:: 3.8
|
|
Added support for Windows.
|
|
|
|
.. versionchanged:: 3.8.1
|
|
The *reuse_address* parameter is no longer supported, as using
|
|
:ref:`socket.SO_REUSEADDR <socket-unix-constants>`
|
|
poses a significant security concern for
|
|
UDP. Explicitly passing ``reuse_address=True`` will raise an exception.
|
|
|
|
When multiple processes with differing UIDs assign sockets to an
|
|
identical UDP socket address with ``SO_REUSEADDR``, incoming packets can
|
|
become randomly distributed among the sockets.
|
|
|
|
For supported platforms, *reuse_port* can be used as a replacement for
|
|
similar functionality. With *reuse_port*,
|
|
:ref:`socket.SO_REUSEPORT <socket-unix-constants>`
|
|
is used instead, which specifically
|
|
prevents processes with differing UIDs from assigning sockets to the same
|
|
socket address.
|
|
|
|
.. versionchanged:: 3.11
|
|
The *reuse_address* parameter, disabled since Python 3.8.1,
|
|
3.7.6 and 3.6.10, has been entirely removed.
|
|
|
|
.. coroutinemethod:: loop.create_unix_connection(protocol_factory, \
|
|
path=None, *, ssl=None, sock=None, \
|
|
server_hostname=None, ssl_handshake_timeout=None, \
|
|
ssl_shutdown_timeout=None)
|
|
|
|
Create a Unix connection.
|
|
|
|
The socket family will be :py:const:`~socket.AF_UNIX`; socket
|
|
type will be :py:const:`~socket.SOCK_STREAM`.
|
|
|
|
A tuple of ``(transport, protocol)`` is returned on success.
|
|
|
|
*path* is the name of a Unix domain socket and is required,
|
|
unless a *sock* parameter is specified. Abstract Unix sockets,
|
|
:class:`str`, :class:`bytes`, and :class:`~pathlib.Path` paths are
|
|
supported.
|
|
|
|
See the documentation of the :meth:`loop.create_connection` method
|
|
for information about arguments to this method.
|
|
|
|
.. availability:: Unix.
|
|
|
|
.. versionchanged:: 3.7
|
|
Added the *ssl_handshake_timeout* parameter.
|
|
The *path* parameter can now be a :term:`path-like object`.
|
|
|
|
.. versionchanged:: 3.11
|
|
|
|
Added the *ssl_shutdown_timeout* parameter.
|
|
|
|
|
|
Creating network servers
|
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
.. _loop_create_server:
|
|
|
|
.. coroutinemethod:: loop.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, reuse_port=None, \
|
|
keep_alive=None, \
|
|
ssl_handshake_timeout=None, \
|
|
ssl_shutdown_timeout=None, \
|
|
start_serving=True)
|
|
|
|
Create a TCP server (socket type :const:`~socket.SOCK_STREAM`) listening
|
|
on *port* of the *host* address.
|
|
|
|
Returns a :class:`Server` object.
|
|
|
|
Arguments:
|
|
|
|
* *protocol_factory* must be a callable returning a
|
|
:ref:`protocol <asyncio-protocol>` implementation.
|
|
|
|
* The *host* parameter can be set to several types which determine where
|
|
the server would be listening:
|
|
|
|
- If *host* is a string, the TCP server is bound to a single network
|
|
interface specified by *host*.
|
|
|
|
- If *host* is a sequence of strings, the TCP server is bound to all
|
|
network interfaces specified by the sequence.
|
|
|
|
- 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).
|
|
|
|
* The *port* parameter can be set to specify which port the server should
|
|
listen on. If ``0`` or ``None`` (the default), a random unused port will
|
|
be selected (note that if *host* resolves to multiple network interfaces,
|
|
a different random port will be selected for each interface).
|
|
|
|
* *family* can be set to either :const:`socket.AF_INET` or
|
|
:const:`~socket.AF_INET6` to force the socket to use IPv4 or IPv6.
|
|
If not set, the *family* will be determined from host name
|
|
(defaults to :const:`~socket.AF_UNSPEC`).
|
|
|
|
* *flags* is a bitmask for :meth:`getaddrinfo`.
|
|
|
|
* *sock* can optionally be specified in order to use a preexisting
|
|
socket object. If specified, *host* and *port* must not be specified.
|
|
|
|
.. note::
|
|
|
|
The *sock* argument transfers ownership of the socket to the
|
|
server created. To close the socket, call the server's
|
|
:meth:`~asyncio.Server.close` method.
|
|
|
|
* *backlog* is the maximum number of queued connections passed to
|
|
:meth:`~socket.socket.listen` (defaults to 100).
|
|
|
|
* *ssl* can be set to an :class:`~ssl.SSLContext` instance to enable
|
|
TLS 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.
|
|
|
|
* *reuse_port* tells the kernel to allow this endpoint to be bound to the
|
|
same port as other existing endpoints are bound to, so long as they all
|
|
set this flag when being created. This option is not supported on
|
|
Windows.
|
|
|
|
* *keep_alive* set to ``True`` keeps connections active by enabling the
|
|
periodic transmission of messages.
|
|
|
|
.. versionchanged:: 3.13
|
|
|
|
Added the *keep_alive* parameter.
|
|
|
|
* *ssl_handshake_timeout* is (for a TLS server) the time in seconds to wait
|
|
for the TLS handshake to complete before aborting the connection.
|
|
``60.0`` seconds if ``None`` (default).
|
|
|
|
* *ssl_shutdown_timeout* is the time in seconds to wait for the SSL shutdown
|
|
to complete before aborting the connection. ``30.0`` seconds if ``None``
|
|
(default).
|
|
|
|
* *start_serving* set to ``True`` (the default) causes the created server
|
|
to start accepting connections immediately. When set to ``False``,
|
|
the user should await on :meth:`Server.start_serving` or
|
|
:meth:`Server.serve_forever` to make the server to start accepting
|
|
connections.
|
|
|
|
.. versionchanged:: 3.5
|
|
|
|
Added support for SSL/TLS in :class:`ProactorEventLoop`.
|
|
|
|
.. versionchanged:: 3.5.1
|
|
|
|
The *host* parameter can be a sequence of strings.
|
|
|
|
.. versionchanged:: 3.6
|
|
|
|
Added *ssl_handshake_timeout* and *start_serving* parameters.
|
|
The socket option :ref:`socket.TCP_NODELAY <socket-unix-constants>` is set by default
|
|
for all TCP connections.
|
|
|
|
.. versionchanged:: 3.11
|
|
|
|
Added the *ssl_shutdown_timeout* parameter.
|
|
|
|
.. seealso::
|
|
|
|
The :func:`start_server` function is a higher-level alternative API
|
|
that returns a pair of :class:`StreamReader` and :class:`StreamWriter`
|
|
that can be used in an async/await code.
|
|
|
|
|
|
.. coroutinemethod:: loop.create_unix_server(protocol_factory, path=None, \
|
|
*, sock=None, backlog=100, ssl=None, \
|
|
ssl_handshake_timeout=None, \
|
|
ssl_shutdown_timeout=None, \
|
|
start_serving=True, cleanup_socket=True)
|
|
|
|
Similar to :meth:`loop.create_server` but works with the
|
|
:py:const:`~socket.AF_UNIX` socket family.
|
|
|
|
*path* is the name of a Unix domain socket, and is required,
|
|
unless a *sock* argument is provided. Abstract Unix sockets,
|
|
:class:`str`, :class:`bytes`, and :class:`~pathlib.Path` paths
|
|
are supported.
|
|
|
|
If *cleanup_socket* is true then the Unix socket will automatically
|
|
be removed from the filesystem when the server is closed, unless the
|
|
socket has been replaced after the server has been created.
|
|
|
|
See the documentation of the :meth:`loop.create_server` method
|
|
for information about arguments to this method.
|
|
|
|
.. availability:: Unix.
|
|
|
|
.. versionchanged:: 3.7
|
|
|
|
Added the *ssl_handshake_timeout* and *start_serving* parameters.
|
|
The *path* parameter can now be a :class:`~pathlib.Path` object.
|
|
|
|
.. versionchanged:: 3.11
|
|
|
|
Added the *ssl_shutdown_timeout* parameter.
|
|
|
|
.. versionchanged:: 3.13
|
|
|
|
Added the *cleanup_socket* parameter.
|
|
|
|
|
|
.. coroutinemethod:: loop.connect_accepted_socket(protocol_factory, \
|
|
sock, *, ssl=None, ssl_handshake_timeout=None, \
|
|
ssl_shutdown_timeout=None)
|
|
|
|
Wrap an already accepted connection into a transport/protocol pair.
|
|
|
|
This method can be used by servers that accept connections outside
|
|
of asyncio but that use asyncio to handle them.
|
|
|
|
Parameters:
|
|
|
|
* *protocol_factory* must be a callable returning a
|
|
:ref:`protocol <asyncio-protocol>` implementation.
|
|
|
|
* *sock* is a preexisting socket object returned from
|
|
:meth:`socket.accept <socket.socket.accept>`.
|
|
|
|
.. note::
|
|
|
|
The *sock* argument transfers ownership of the socket to the
|
|
transport created. To close the socket, call the transport's
|
|
:meth:`~asyncio.BaseTransport.close` method.
|
|
|
|
* *ssl* can be set to an :class:`~ssl.SSLContext` to enable SSL over
|
|
the accepted connections.
|
|
|
|
* *ssl_handshake_timeout* is (for an SSL connection) the time in seconds to
|
|
wait for the SSL handshake to complete before aborting the connection.
|
|
``60.0`` seconds if ``None`` (default).
|
|
|
|
* *ssl_shutdown_timeout* is the time in seconds to wait for the SSL shutdown
|
|
to complete before aborting the connection. ``30.0`` seconds if ``None``
|
|
(default).
|
|
|
|
Returns a ``(transport, protocol)`` pair.
|
|
|
|
.. versionadded:: 3.5.3
|
|
|
|
.. versionchanged:: 3.7
|
|
|
|
Added the *ssl_handshake_timeout* parameter.
|
|
|
|
.. versionchanged:: 3.11
|
|
|
|
Added the *ssl_shutdown_timeout* parameter.
|
|
|
|
|
|
Transferring files
|
|
^^^^^^^^^^^^^^^^^^
|
|
|
|
.. coroutinemethod:: loop.sendfile(transport, file, \
|
|
offset=0, count=None, *, fallback=True)
|
|
|
|
Send a *file* over a *transport*. Return the total number of bytes
|
|
sent.
|
|
|
|
The method uses high-performance :meth:`os.sendfile` if available.
|
|
|
|
*file* must be a regular file object opened in binary mode.
|
|
|
|
*offset* tells from where to start reading the file. If specified,
|
|
*count* is the total number of bytes to transmit as opposed to
|
|
sending the file until EOF is reached. File position is always updated,
|
|
even when this method raises an error, and
|
|
:meth:`file.tell() <io.IOBase.tell>` can be used to obtain the actual
|
|
number of bytes sent.
|
|
|
|
*fallback* set to ``True`` makes asyncio to manually read and send
|
|
the file when the platform does not support the sendfile system call
|
|
(e.g. Windows or SSL socket on Unix).
|
|
|
|
Raise :exc:`SendfileNotAvailableError` if the system does not support
|
|
the *sendfile* syscall and *fallback* is ``False``.
|
|
|
|
.. versionadded:: 3.7
|
|
|
|
|
|
TLS Upgrade
|
|
^^^^^^^^^^^
|
|
|
|
.. coroutinemethod:: loop.start_tls(transport, protocol, \
|
|
sslcontext, *, server_side=False, \
|
|
server_hostname=None, ssl_handshake_timeout=None, \
|
|
ssl_shutdown_timeout=None)
|
|
|
|
Upgrade an existing transport-based connection to TLS.
|
|
|
|
Create a TLS coder/decoder instance and insert it between the *transport*
|
|
and the *protocol*. The coder/decoder implements both *transport*-facing
|
|
protocol and *protocol*-facing transport.
|
|
|
|
Return the created two-interface instance. After *await*, the *protocol*
|
|
must stop using the original *transport* and communicate with the returned
|
|
object only because the coder caches *protocol*-side data and sporadically
|
|
exchanges extra TLS session packets with *transport*.
|
|
|
|
In some situations (e.g. when the passed transport is already closing) this
|
|
may return ``None``.
|
|
|
|
Parameters:
|
|
|
|
* *transport* and *protocol* instances that methods like
|
|
:meth:`~loop.create_server` and
|
|
:meth:`~loop.create_connection` return.
|
|
|
|
* *sslcontext*: a configured instance of :class:`~ssl.SSLContext`.
|
|
|
|
* *server_side* pass ``True`` when a server-side connection is being
|
|
upgraded (like the one created by :meth:`~loop.create_server`).
|
|
|
|
* *server_hostname*: sets or overrides the host name that the target
|
|
server's certificate will be matched against.
|
|
|
|
* *ssl_handshake_timeout* is (for a TLS connection) the time in seconds to
|
|
wait for the TLS handshake to complete before aborting the connection.
|
|
``60.0`` seconds if ``None`` (default).
|
|
|
|
* *ssl_shutdown_timeout* is the time in seconds to wait for the SSL shutdown
|
|
to complete before aborting the connection. ``30.0`` seconds if ``None``
|
|
(default).
|
|
|
|
.. versionadded:: 3.7
|
|
|
|
.. versionchanged:: 3.11
|
|
|
|
Added the *ssl_shutdown_timeout* parameter.
|
|
|
|
|
|
|
|
Watching file descriptors
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
.. method:: loop.add_reader(fd, callback, *args)
|
|
|
|
Start monitoring the *fd* file descriptor for read availability and
|
|
invoke *callback* with the specified arguments once *fd* is available for
|
|
reading.
|
|
|
|
.. method:: loop.remove_reader(fd)
|
|
|
|
Stop monitoring the *fd* file descriptor for read availability. Returns
|
|
``True`` if *fd* was previously being monitored for reads.
|
|
|
|
.. method:: loop.add_writer(fd, callback, *args)
|
|
|
|
Start monitoring the *fd* file descriptor for write availability and
|
|
invoke *callback* with the specified arguments once *fd* is available for
|
|
writing.
|
|
|
|
Use :func:`functools.partial` :ref:`to pass keyword arguments
|
|
<asyncio-pass-keywords>` to *callback*.
|
|
|
|
.. method:: loop.remove_writer(fd)
|
|
|
|
Stop monitoring the *fd* file descriptor for write availability. Returns
|
|
``True`` if *fd* was previously being monitored for writes.
|
|
|
|
See also :ref:`Platform Support <asyncio-platform-support>` section
|
|
for some limitations of these methods.
|
|
|
|
|
|
Working with socket objects directly
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
In general, protocol implementations that use transport-based APIs
|
|
such as :meth:`loop.create_connection` and :meth:`loop.create_server`
|
|
are faster than implementations that work with sockets directly.
|
|
However, there are some use cases when performance is not critical, and
|
|
working with :class:`~socket.socket` objects directly is more
|
|
convenient.
|
|
|
|
.. coroutinemethod:: loop.sock_recv(sock, nbytes)
|
|
|
|
Receive up to *nbytes* from *sock*. Asynchronous version of
|
|
:meth:`socket.recv() <socket.socket.recv>`.
|
|
|
|
Return the received data as a bytes object.
|
|
|
|
*sock* must be a non-blocking socket.
|
|
|
|
.. versionchanged:: 3.7
|
|
Even though this method was always documented as a coroutine
|
|
method, releases before Python 3.7 returned a :class:`Future`.
|
|
Since Python 3.7 this is an ``async def`` method.
|
|
|
|
.. coroutinemethod:: loop.sock_recv_into(sock, buf)
|
|
|
|
Receive data from *sock* into the *buf* buffer. Modeled after the blocking
|
|
:meth:`socket.recv_into() <socket.socket.recv_into>` method.
|
|
|
|
Return the number of bytes written to the buffer.
|
|
|
|
*sock* must be a non-blocking socket.
|
|
|
|
.. versionadded:: 3.7
|
|
|
|
.. coroutinemethod:: loop.sock_recvfrom(sock, bufsize)
|
|
|
|
Receive a datagram of up to *bufsize* from *sock*. Asynchronous version of
|
|
:meth:`socket.recvfrom() <socket.socket.recvfrom>`.
|
|
|
|
Return a tuple of (received data, remote address).
|
|
|
|
*sock* must be a non-blocking socket.
|
|
|
|
.. versionadded:: 3.11
|
|
|
|
.. coroutinemethod:: loop.sock_recvfrom_into(sock, buf, nbytes=0)
|
|
|
|
Receive a datagram of up to *nbytes* from *sock* into *buf*.
|
|
Asynchronous version of
|
|
:meth:`socket.recvfrom_into() <socket.socket.recvfrom_into>`.
|
|
|
|
Return a tuple of (number of bytes received, remote address).
|
|
|
|
*sock* must be a non-blocking socket.
|
|
|
|
.. versionadded:: 3.11
|
|
|
|
.. coroutinemethod:: loop.sock_sendall(sock, data)
|
|
|
|
Send *data* to the *sock* socket. Asynchronous version of
|
|
:meth:`socket.sendall() <socket.socket.sendall>`.
|
|
|
|
This method continues to send to the socket until either all data
|
|
in *data* has been sent or an error occurs. ``None`` is returned
|
|
on success. On error, an exception is raised. Additionally, there is no way
|
|
to determine how much data, if any, was successfully processed by the
|
|
receiving end of the connection.
|
|
|
|
*sock* must be a non-blocking socket.
|
|
|
|
.. versionchanged:: 3.7
|
|
Even though the method was always documented as a coroutine
|
|
method, before Python 3.7 it returned a :class:`Future`.
|
|
Since Python 3.7, this is an ``async def`` method.
|
|
|
|
.. coroutinemethod:: loop.sock_sendto(sock, data, address)
|
|
|
|
Send a datagram from *sock* to *address*.
|
|
Asynchronous version of
|
|
:meth:`socket.sendto() <socket.socket.sendto>`.
|
|
|
|
Return the number of bytes sent.
|
|
|
|
*sock* must be a non-blocking socket.
|
|
|
|
.. versionadded:: 3.11
|
|
|
|
.. coroutinemethod:: loop.sock_connect(sock, address)
|
|
|
|
Connect *sock* to a remote socket at *address*.
|
|
|
|
Asynchronous version of :meth:`socket.connect() <socket.socket.connect>`.
|
|
|
|
*sock* must be a non-blocking socket.
|
|
|
|
.. versionchanged:: 3.5.2
|
|
``address`` no longer needs to be resolved. ``sock_connect``
|
|
will try to check if the *address* is already resolved by calling
|
|
:func:`socket.inet_pton`. If not,
|
|
:meth:`loop.getaddrinfo` will be used to resolve the
|
|
*address*.
|
|
|
|
.. seealso::
|
|
|
|
:meth:`loop.create_connection`
|
|
and :func:`asyncio.open_connection() <open_connection>`.
|
|
|
|
|
|
.. coroutinemethod:: loop.sock_accept(sock)
|
|
|
|
Accept a connection. Modeled after the blocking
|
|
:meth:`socket.accept() <socket.socket.accept>` method.
|
|
|
|
The socket must be bound to an address and listening
|
|
for connections. The return value is a pair ``(conn, address)`` where *conn*
|
|
is a *new* socket object usable to send and receive data on the connection,
|
|
and *address* is the address bound to the socket on the other end of the
|
|
connection.
|
|
|
|
*sock* must be a non-blocking socket.
|
|
|
|
.. versionchanged:: 3.7
|
|
Even though the method was always documented as a coroutine
|
|
method, before Python 3.7 it returned a :class:`Future`.
|
|
Since Python 3.7, this is an ``async def`` method.
|
|
|
|
.. seealso::
|
|
|
|
:meth:`loop.create_server` and :func:`start_server`.
|
|
|
|
.. coroutinemethod:: loop.sock_sendfile(sock, file, offset=0, count=None, \
|
|
*, fallback=True)
|
|
|
|
Send a file using high-performance :mod:`os.sendfile` if possible.
|
|
Return the total number of bytes sent.
|
|
|
|
Asynchronous version of :meth:`socket.sendfile() <socket.socket.sendfile>`.
|
|
|
|
*sock* must be a non-blocking :const:`socket.SOCK_STREAM`
|
|
:class:`~socket.socket`.
|
|
|
|
*file* must be a regular file object open in binary mode.
|
|
|
|
*offset* tells from where to start reading the file. If specified,
|
|
*count* is the total number of bytes to transmit as opposed to
|
|
sending the file until EOF is reached. File position is always updated,
|
|
even when this method raises an error, and
|
|
:meth:`file.tell() <io.IOBase.tell>` can be used to obtain the actual
|
|
number of bytes sent.
|
|
|
|
*fallback*, when set to ``True``, makes asyncio manually read and send
|
|
the file when the platform does not support the sendfile syscall
|
|
(e.g. Windows or SSL socket on Unix).
|
|
|
|
Raise :exc:`SendfileNotAvailableError` if the system does not support
|
|
*sendfile* syscall and *fallback* is ``False``.
|
|
|
|
*sock* must be a non-blocking socket.
|
|
|
|
.. versionadded:: 3.7
|
|
|
|
|
|
DNS
|
|
^^^
|
|
|
|
.. coroutinemethod:: loop.getaddrinfo(host, port, *, family=0, \
|
|
type=0, proto=0, flags=0)
|
|
|
|
Asynchronous version of :meth:`socket.getaddrinfo`.
|
|
|
|
.. coroutinemethod:: loop.getnameinfo(sockaddr, flags=0)
|
|
|
|
Asynchronous version of :meth:`socket.getnameinfo`.
|
|
|
|
.. versionchanged:: 3.7
|
|
Both *getaddrinfo* and *getnameinfo* methods were always documented
|
|
to return a coroutine, but prior to Python 3.7 they were, in fact,
|
|
returning :class:`asyncio.Future` objects. Starting with Python 3.7
|
|
both methods are coroutines.
|
|
|
|
|
|
Working with pipes
|
|
^^^^^^^^^^^^^^^^^^
|
|
|
|
.. coroutinemethod:: loop.connect_read_pipe(protocol_factory, pipe)
|
|
|
|
Register the read end of *pipe* in the event loop.
|
|
|
|
*protocol_factory* must be a callable returning an
|
|
:ref:`asyncio protocol <asyncio-protocol>` implementation.
|
|
|
|
*pipe* is a :term:`file-like object <file object>`.
|
|
|
|
Return pair ``(transport, protocol)``, where *transport* supports
|
|
the :class:`ReadTransport` interface and *protocol* is an object
|
|
instantiated by the *protocol_factory*.
|
|
|
|
With :class:`SelectorEventLoop` event loop, the *pipe* is set to
|
|
non-blocking mode.
|
|
|
|
.. coroutinemethod:: loop.connect_write_pipe(protocol_factory, pipe)
|
|
|
|
Register the write end of *pipe* in the event loop.
|
|
|
|
*protocol_factory* must be a callable returning an
|
|
:ref:`asyncio protocol <asyncio-protocol>` implementation.
|
|
|
|
*pipe* is :term:`file-like object <file object>`.
|
|
|
|
Return pair ``(transport, protocol)``, where *transport* supports
|
|
:class:`WriteTransport` interface and *protocol* is an object
|
|
instantiated by the *protocol_factory*.
|
|
|
|
With :class:`SelectorEventLoop` event loop, the *pipe* is set to
|
|
non-blocking mode.
|
|
|
|
.. note::
|
|
|
|
:class:`SelectorEventLoop` does not support the above methods on
|
|
Windows. Use :class:`ProactorEventLoop` instead for Windows.
|
|
|
|
.. seealso::
|
|
|
|
The :meth:`loop.subprocess_exec` and
|
|
:meth:`loop.subprocess_shell` methods.
|
|
|
|
|
|
Unix signals
|
|
^^^^^^^^^^^^
|
|
|
|
.. _loop_add_signal_handler:
|
|
|
|
.. method:: loop.add_signal_handler(signum, callback, *args)
|
|
|
|
Set *callback* as the handler for the *signum* signal.
|
|
|
|
The callback will be invoked by *loop*, along with other queued callbacks
|
|
and runnable coroutines of that event loop. Unlike signal handlers
|
|
registered using :func:`signal.signal`, a callback registered with this
|
|
function is allowed to interact with the event loop.
|
|
|
|
Raise :exc:`ValueError` if the signal number is invalid or uncatchable.
|
|
Raise :exc:`RuntimeError` if there is a problem setting up the handler.
|
|
|
|
Use :func:`functools.partial` :ref:`to pass keyword arguments
|
|
<asyncio-pass-keywords>` to *callback*.
|
|
|
|
Like :func:`signal.signal`, this function must be invoked in the main
|
|
thread.
|
|
|
|
.. method:: loop.remove_signal_handler(sig)
|
|
|
|
Remove the handler for the *sig* signal.
|
|
|
|
Return ``True`` if the signal handler was removed, or ``False`` if
|
|
no handler was set for the given signal.
|
|
|
|
.. availability:: Unix.
|
|
|
|
.. seealso::
|
|
|
|
The :mod:`signal` module.
|
|
|
|
|
|
Executing code in thread or process pools
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
.. awaitablemethod:: loop.run_in_executor(executor, func, *args)
|
|
|
|
Arrange for *func* to be called in the specified executor.
|
|
|
|
The *executor* argument should be an :class:`concurrent.futures.Executor`
|
|
instance. The default executor is used if *executor* is ``None``.
|
|
|
|
Example::
|
|
|
|
import asyncio
|
|
import concurrent.futures
|
|
|
|
def blocking_io():
|
|
# File operations (such as logging) can block the
|
|
# event loop: run them in a thread pool.
|
|
with open('/dev/urandom', 'rb') as f:
|
|
return f.read(100)
|
|
|
|
def cpu_bound():
|
|
# CPU-bound operations will block the event loop:
|
|
# in general it is preferable to run them in a
|
|
# process pool.
|
|
return sum(i * i for i in range(10 ** 7))
|
|
|
|
async def main():
|
|
loop = asyncio.get_running_loop()
|
|
|
|
## Options:
|
|
|
|
# 1. Run in the default loop's executor:
|
|
result = await loop.run_in_executor(
|
|
None, blocking_io)
|
|
print('default thread pool', result)
|
|
|
|
# 2. Run in a custom thread pool:
|
|
with concurrent.futures.ThreadPoolExecutor() as pool:
|
|
result = await loop.run_in_executor(
|
|
pool, blocking_io)
|
|
print('custom thread pool', result)
|
|
|
|
# 3. Run in a custom process pool:
|
|
with concurrent.futures.ProcessPoolExecutor() as pool:
|
|
result = await loop.run_in_executor(
|
|
pool, cpu_bound)
|
|
print('custom process pool', result)
|
|
|
|
if __name__ == '__main__':
|
|
asyncio.run(main())
|
|
|
|
Note that the entry point guard (``if __name__ == '__main__'``)
|
|
is required for option 3 due to the peculiarities of :mod:`multiprocessing`,
|
|
which is used by :class:`~concurrent.futures.ProcessPoolExecutor`.
|
|
See :ref:`Safe importing of main module <multiprocessing-safe-main-import>`.
|
|
|
|
This method returns a :class:`asyncio.Future` object.
|
|
|
|
Use :func:`functools.partial` :ref:`to pass keyword arguments
|
|
<asyncio-pass-keywords>` to *func*.
|
|
|
|
.. versionchanged:: 3.5.3
|
|
:meth:`loop.run_in_executor` no longer configures the
|
|
``max_workers`` of the thread pool executor it creates, instead
|
|
leaving it up to the thread pool executor
|
|
(:class:`~concurrent.futures.ThreadPoolExecutor`) to set the
|
|
default.
|
|
|
|
.. method:: loop.set_default_executor(executor)
|
|
|
|
Set *executor* as the default executor used by :meth:`run_in_executor`.
|
|
*executor* must be an instance of
|
|
:class:`~concurrent.futures.ThreadPoolExecutor`.
|
|
|
|
.. versionchanged:: 3.11
|
|
*executor* must be an instance of
|
|
:class:`~concurrent.futures.ThreadPoolExecutor`.
|
|
|
|
|
|
Error Handling API
|
|
^^^^^^^^^^^^^^^^^^
|
|
|
|
Allows customizing how exceptions are handled in the event loop.
|
|
|
|
.. method:: loop.set_exception_handler(handler)
|
|
|
|
Set *handler* as the new event loop exception handler.
|
|
|
|
If *handler* is ``None``, the default exception handler will
|
|
be set. Otherwise, *handler* must be a callable with the signature
|
|
matching ``(loop, context)``, where ``loop``
|
|
is a reference to the active event loop, and ``context``
|
|
is a ``dict`` object containing the details of the exception
|
|
(see :meth:`call_exception_handler` documentation for details
|
|
about context).
|
|
|
|
If the handler is called on behalf of a :class:`~asyncio.Task` or
|
|
:class:`~asyncio.Handle`, it is run in the
|
|
:class:`contextvars.Context` of that task or callback handle.
|
|
|
|
.. versionchanged:: 3.12
|
|
|
|
The handler may be called in the :class:`~contextvars.Context`
|
|
of the task or handle where the exception originated.
|
|
|
|
.. method:: loop.get_exception_handler()
|
|
|
|
Return the current exception handler, or ``None`` if no custom
|
|
exception handler was set.
|
|
|
|
.. versionadded:: 3.5.2
|
|
|
|
.. method:: loop.default_exception_handler(context)
|
|
|
|
Default exception handler.
|
|
|
|
This is called when an exception occurs and no exception
|
|
handler is set. This can be called by a custom exception
|
|
handler that wants to defer to the default handler behavior.
|
|
|
|
*context* parameter has the same meaning as in
|
|
:meth:`call_exception_handler`.
|
|
|
|
.. method:: loop.call_exception_handler(context)
|
|
|
|
Call the current event loop exception handler.
|
|
|
|
*context* is a ``dict`` object containing the following keys
|
|
(new keys may be introduced in future Python versions):
|
|
|
|
* 'message': Error message;
|
|
* 'exception' (optional): Exception object;
|
|
* 'future' (optional): :class:`asyncio.Future` instance;
|
|
* 'task' (optional): :class:`asyncio.Task` instance;
|
|
* 'handle' (optional): :class:`asyncio.Handle` instance;
|
|
* 'protocol' (optional): :ref:`Protocol <asyncio-protocol>` instance;
|
|
* 'transport' (optional): :ref:`Transport <asyncio-transport>` instance;
|
|
* 'socket' (optional): :class:`socket.socket` instance;
|
|
* 'asyncgen' (optional): Asynchronous generator that caused
|
|
the exception.
|
|
|
|
.. note::
|
|
|
|
This method should not be overloaded in subclassed
|
|
event loops. For custom exception handling, use
|
|
the :meth:`set_exception_handler()` method.
|
|
|
|
Enabling debug mode
|
|
^^^^^^^^^^^^^^^^^^^
|
|
|
|
.. method:: loop.get_debug()
|
|
|
|
Get the debug mode (:class:`bool`) of the event loop.
|
|
|
|
The default value is ``True`` if the environment variable
|
|
:envvar:`PYTHONASYNCIODEBUG` is set to a non-empty string, ``False``
|
|
otherwise.
|
|
|
|
.. method:: loop.set_debug(enabled: bool)
|
|
|
|
Set the debug mode of the event loop.
|
|
|
|
.. versionchanged:: 3.7
|
|
|
|
The new :ref:`Python Development Mode <devmode>` can now also be used
|
|
to enable the debug mode.
|
|
|
|
.. attribute:: loop.slow_callback_duration
|
|
|
|
This attribute can be used to set the
|
|
minimum execution duration in seconds that is considered "slow".
|
|
When debug mode is enabled, "slow" callbacks are logged.
|
|
|
|
Default value is 100 milliseconds.
|
|
|
|
.. seealso::
|
|
|
|
The :ref:`debug mode of asyncio <asyncio-debug-mode>`.
|
|
|
|
|
|
Running Subprocesses
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Methods described in this subsections are low-level. In regular
|
|
async/await code consider using the high-level
|
|
:func:`asyncio.create_subprocess_shell` and
|
|
:func:`asyncio.create_subprocess_exec` convenience functions instead.
|
|
|
|
.. note::
|
|
|
|
On Windows, the default event loop :class:`ProactorEventLoop` supports
|
|
subprocesses, whereas :class:`SelectorEventLoop` does not. See
|
|
:ref:`Subprocess Support on Windows <asyncio-windows-subprocess>` for
|
|
details.
|
|
|
|
.. _loop_subprocess_exec:
|
|
|
|
.. coroutinemethod:: loop.subprocess_exec(protocol_factory, *args, \
|
|
stdin=subprocess.PIPE, stdout=subprocess.PIPE, \
|
|
stderr=subprocess.PIPE, **kwargs)
|
|
|
|
Create a subprocess from one or more string arguments specified by
|
|
*args*.
|
|
|
|
*args* must be a list of strings represented by:
|
|
|
|
* :class:`str`;
|
|
* or :class:`bytes`, encoded to the
|
|
:ref:`filesystem encoding <filesystem-encoding>`.
|
|
|
|
The first string specifies the program executable,
|
|
and the remaining strings specify the arguments. Together, string
|
|
arguments form the ``argv`` of the program.
|
|
|
|
This is similar to the standard library :class:`subprocess.Popen`
|
|
class called with ``shell=False`` and the list of strings passed as
|
|
the first argument; however, where :class:`~subprocess.Popen` takes
|
|
a single argument which is list of strings, *subprocess_exec*
|
|
takes multiple string arguments.
|
|
|
|
The *protocol_factory* must be a callable returning a subclass of the
|
|
:class:`asyncio.SubprocessProtocol` class.
|
|
|
|
Other parameters:
|
|
|
|
* *stdin* can be any of these:
|
|
|
|
* a file-like object
|
|
* an existing file descriptor (a positive integer), for example those created with :meth:`os.pipe()`
|
|
* the :const:`subprocess.PIPE` constant (default) which will create a new
|
|
pipe and connect it,
|
|
* the value ``None`` which will make the subprocess inherit the file
|
|
descriptor from this process
|
|
* the :const:`subprocess.DEVNULL` constant which indicates that the
|
|
special :data:`os.devnull` file will be used
|
|
|
|
* *stdout* can be any of these:
|
|
|
|
* a file-like object
|
|
* the :const:`subprocess.PIPE` constant (default) which will create a new
|
|
pipe and connect it,
|
|
* the value ``None`` which will make the subprocess inherit the file
|
|
descriptor from this process
|
|
* the :const:`subprocess.DEVNULL` constant which indicates that the
|
|
special :data:`os.devnull` file will be used
|
|
|
|
* *stderr* can be any of these:
|
|
|
|
* a file-like object
|
|
* the :const:`subprocess.PIPE` constant (default) which will create a new
|
|
pipe and connect it,
|
|
* the value ``None`` which will make the subprocess inherit the file
|
|
descriptor from this process
|
|
* the :const:`subprocess.DEVNULL` constant which indicates that the
|
|
special :data:`os.devnull` file will be used
|
|
* the :const:`subprocess.STDOUT` constant which will connect the standard
|
|
error stream to the process' standard output stream
|
|
|
|
* All other keyword arguments are passed to :class:`subprocess.Popen`
|
|
without interpretation, except for *bufsize*, *universal_newlines*,
|
|
*shell*, *text*, *encoding* and *errors*, which should not be specified
|
|
at all.
|
|
|
|
The ``asyncio`` subprocess API does not support decoding the streams
|
|
as text. :func:`bytes.decode` can be used to convert the bytes returned
|
|
from the stream to text.
|
|
|
|
If a file-like object passed as *stdin*, *stdout* or *stderr* represents a
|
|
pipe, then the other side of this pipe should be registered with
|
|
:meth:`~loop.connect_write_pipe` or :meth:`~loop.connect_read_pipe` for use
|
|
with the event loop.
|
|
|
|
See the constructor of the :class:`subprocess.Popen` class
|
|
for documentation on other arguments.
|
|
|
|
Returns a pair of ``(transport, protocol)``, where *transport*
|
|
conforms to the :class:`asyncio.SubprocessTransport` base class and
|
|
*protocol* is an object instantiated by the *protocol_factory*.
|
|
|
|
.. coroutinemethod:: loop.subprocess_shell(protocol_factory, cmd, *, \
|
|
stdin=subprocess.PIPE, stdout=subprocess.PIPE, \
|
|
stderr=subprocess.PIPE, **kwargs)
|
|
|
|
Create a subprocess from *cmd*, which can be a :class:`str` or a
|
|
:class:`bytes` string encoded to the
|
|
:ref:`filesystem encoding <filesystem-encoding>`,
|
|
using the platform's "shell" syntax.
|
|
|
|
This is similar to the standard library :class:`subprocess.Popen`
|
|
class called with ``shell=True``.
|
|
|
|
The *protocol_factory* must be a callable returning a subclass of the
|
|
:class:`SubprocessProtocol` class.
|
|
|
|
See :meth:`~loop.subprocess_exec` for more details about
|
|
the remaining arguments.
|
|
|
|
Returns a pair of ``(transport, protocol)``, where *transport*
|
|
conforms to the :class:`SubprocessTransport` base class and
|
|
*protocol* is an object instantiated by the *protocol_factory*.
|
|
|
|
.. note::
|
|
It is the application's responsibility to ensure that all whitespace
|
|
and special characters are quoted appropriately to avoid `shell injection
|
|
<https://en.wikipedia.org/wiki/Shell_injection#Shell_injection>`_
|
|
vulnerabilities. The :func:`shlex.quote` function can be used to
|
|
properly escape whitespace and special characters in strings that
|
|
are going to be used to construct shell commands.
|
|
|
|
|
|
Callback Handles
|
|
================
|
|
|
|
.. class:: Handle
|
|
|
|
A callback wrapper object returned by :meth:`loop.call_soon`,
|
|
:meth:`loop.call_soon_threadsafe`.
|
|
|
|
.. method:: get_context()
|
|
|
|
Return the :class:`contextvars.Context` object
|
|
associated with the handle.
|
|
|
|
.. versionadded:: 3.12
|
|
|
|
.. method:: cancel()
|
|
|
|
Cancel the callback. If the callback has already been canceled
|
|
or executed, this method has no effect.
|
|
|
|
.. method:: cancelled()
|
|
|
|
Return ``True`` if the callback was cancelled.
|
|
|
|
.. versionadded:: 3.7
|
|
|
|
.. class:: TimerHandle
|
|
|
|
A callback wrapper object returned by :meth:`loop.call_later`,
|
|
and :meth:`loop.call_at`.
|
|
|
|
This class is a subclass of :class:`Handle`.
|
|
|
|
.. method:: when()
|
|
|
|
Return a scheduled callback time as :class:`float` seconds.
|
|
|
|
The time is an absolute timestamp, using the same time
|
|
reference as :meth:`loop.time`.
|
|
|
|
.. versionadded:: 3.7
|
|
|
|
|
|
Server Objects
|
|
==============
|
|
|
|
Server objects are created by :meth:`loop.create_server`,
|
|
:meth:`loop.create_unix_server`, :func:`start_server`,
|
|
and :func:`start_unix_server` functions.
|
|
|
|
Do not instantiate the :class:`Server` class directly.
|
|
|
|
.. class:: Server
|
|
|
|
*Server* objects are asynchronous context managers. When used in an
|
|
``async with`` statement, it's guaranteed that the Server object is
|
|
closed and not accepting new connections when the ``async with``
|
|
statement is completed::
|
|
|
|
srv = await loop.create_server(...)
|
|
|
|
async with srv:
|
|
# some code
|
|
|
|
# At this point, srv is closed and no longer accepts new connections.
|
|
|
|
|
|
.. versionchanged:: 3.7
|
|
Server object is an asynchronous context manager since Python 3.7.
|
|
|
|
.. versionchanged:: 3.11
|
|
This class was exposed publicly as ``asyncio.Server`` in Python 3.9.11, 3.10.3 and 3.11.
|
|
|
|
.. method:: close()
|
|
|
|
Stop serving: close listening sockets and set the :attr:`sockets`
|
|
attribute to ``None``.
|
|
|
|
The sockets that represent existing incoming client connections
|
|
are left open.
|
|
|
|
The server is closed asynchronously; use the :meth:`wait_closed`
|
|
coroutine to wait until the server is closed (and no more
|
|
connections are active).
|
|
|
|
.. method:: close_clients()
|
|
|
|
Close all existing incoming client connections.
|
|
|
|
Calls :meth:`~asyncio.BaseTransport.close` on all associated
|
|
transports.
|
|
|
|
:meth:`close` should be called before :meth:`close_clients` when
|
|
closing the server to avoid races with new clients connecting.
|
|
|
|
.. versionadded:: 3.13
|
|
|
|
.. method:: abort_clients()
|
|
|
|
Close all existing incoming client connections immediately,
|
|
without waiting for pending operations to complete.
|
|
|
|
Calls :meth:`~asyncio.WriteTransport.abort` on all associated
|
|
transports.
|
|
|
|
:meth:`close` should be called before :meth:`abort_clients` when
|
|
closing the server to avoid races with new clients connecting.
|
|
|
|
.. versionadded:: 3.13
|
|
|
|
.. method:: get_loop()
|
|
|
|
Return the event loop associated with the server object.
|
|
|
|
.. versionadded:: 3.7
|
|
|
|
.. coroutinemethod:: start_serving()
|
|
|
|
Start accepting connections.
|
|
|
|
This method is idempotent, so it can be called when
|
|
the server is already serving.
|
|
|
|
The *start_serving* keyword-only parameter to
|
|
:meth:`loop.create_server` and
|
|
:meth:`asyncio.start_server` allows creating a Server object
|
|
that is not accepting connections initially. In this case
|
|
``Server.start_serving()``, or :meth:`Server.serve_forever` can be used
|
|
to make the Server start accepting connections.
|
|
|
|
.. versionadded:: 3.7
|
|
|
|
.. coroutinemethod:: serve_forever()
|
|
|
|
Start accepting connections until the coroutine is cancelled.
|
|
Cancellation of ``serve_forever`` task causes the server
|
|
to be closed.
|
|
|
|
This method can be called if the server is already accepting
|
|
connections. Only one ``serve_forever`` task can exist per
|
|
one *Server* object.
|
|
|
|
Example::
|
|
|
|
async def client_connected(reader, writer):
|
|
# Communicate with the client with
|
|
# reader/writer streams. For example:
|
|
await reader.readline()
|
|
|
|
async def main(host, port):
|
|
srv = await asyncio.start_server(
|
|
client_connected, host, port)
|
|
await srv.serve_forever()
|
|
|
|
asyncio.run(main('127.0.0.1', 0))
|
|
|
|
.. versionadded:: 3.7
|
|
|
|
.. method:: is_serving()
|
|
|
|
Return ``True`` if the server is accepting new connections.
|
|
|
|
.. versionadded:: 3.7
|
|
|
|
.. coroutinemethod:: wait_closed()
|
|
|
|
Wait until the :meth:`close` method completes and all active
|
|
connections have finished.
|
|
|
|
.. attribute:: sockets
|
|
|
|
List of socket-like objects, ``asyncio.trsock.TransportSocket``, which
|
|
the server is listening on.
|
|
|
|
.. versionchanged:: 3.7
|
|
Prior to Python 3.7 ``Server.sockets`` used to return an
|
|
internal list of server sockets directly. In 3.7 a copy
|
|
of that list is returned.
|
|
|
|
|
|
.. _asyncio-event-loops:
|
|
.. _asyncio-event-loop-implementations:
|
|
|
|
Event Loop Implementations
|
|
==========================
|
|
|
|
asyncio ships with two different event loop implementations:
|
|
:class:`SelectorEventLoop` and :class:`ProactorEventLoop`.
|
|
|
|
By default asyncio is configured to use :class:`EventLoop`.
|
|
|
|
|
|
.. class:: SelectorEventLoop
|
|
|
|
A subclass of :class:`AbstractEventLoop` based on the
|
|
:mod:`selectors` module.
|
|
|
|
Uses the most efficient *selector* available for the given
|
|
platform. It is also possible to manually configure the
|
|
exact selector implementation to be used::
|
|
|
|
import asyncio
|
|
import selectors
|
|
|
|
class MyPolicy(asyncio.DefaultEventLoopPolicy):
|
|
def new_event_loop(self):
|
|
selector = selectors.SelectSelector()
|
|
return asyncio.SelectorEventLoop(selector)
|
|
|
|
asyncio.set_event_loop_policy(MyPolicy())
|
|
|
|
|
|
.. availability:: Unix, Windows.
|
|
|
|
|
|
.. class:: ProactorEventLoop
|
|
|
|
A subclass of :class:`AbstractEventLoop` for Windows that uses "I/O Completion Ports" (IOCP).
|
|
|
|
.. availability:: Windows.
|
|
|
|
.. seealso::
|
|
|
|
`MSDN documentation on I/O Completion Ports
|
|
<https://docs.microsoft.com/en-ca/windows/desktop/FileIO/i-o-completion-ports>`_.
|
|
|
|
.. class:: EventLoop
|
|
|
|
An alias to the most efficient available subclass of :class:`AbstractEventLoop` for the given
|
|
platform.
|
|
|
|
It is an alias to :class:`SelectorEventLoop` on Unix and :class:`ProactorEventLoop` on Windows.
|
|
|
|
.. versionadded:: 3.13
|
|
|
|
.. class:: AbstractEventLoop
|
|
|
|
Abstract base class for asyncio-compliant event loops.
|
|
|
|
The :ref:`asyncio-event-loop-methods` section lists all
|
|
methods that an alternative implementation of ``AbstractEventLoop``
|
|
should have defined.
|
|
|
|
|
|
Examples
|
|
========
|
|
|
|
Note that all examples in this section **purposefully** show how
|
|
to use the low-level event loop APIs, such as :meth:`loop.run_forever`
|
|
and :meth:`loop.call_soon`. Modern asyncio applications rarely
|
|
need to be written this way; consider using the high-level functions
|
|
like :func:`asyncio.run`.
|
|
|
|
|
|
.. _asyncio_example_lowlevel_helloworld:
|
|
|
|
Hello World with call_soon()
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
An example using the :meth:`loop.call_soon` method to schedule a
|
|
callback. The callback displays ``"Hello World"`` and then stops the
|
|
event loop::
|
|
|
|
import asyncio
|
|
|
|
def hello_world(loop):
|
|
"""A callback to print 'Hello World' and stop the event loop"""
|
|
print('Hello World')
|
|
loop.stop()
|
|
|
|
loop = asyncio.new_event_loop()
|
|
|
|
# Schedule a call to hello_world()
|
|
loop.call_soon(hello_world, loop)
|
|
|
|
# Blocking call interrupted by loop.stop()
|
|
try:
|
|
loop.run_forever()
|
|
finally:
|
|
loop.close()
|
|
|
|
.. seealso::
|
|
|
|
A similar :ref:`Hello World <coroutine>`
|
|
example created with a coroutine and the :func:`run` function.
|
|
|
|
|
|
.. _asyncio_example_call_later:
|
|
|
|
Display the current date with call_later()
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
An example of a callback displaying the current date every second. The
|
|
callback uses the :meth:`loop.call_later` method to reschedule itself
|
|
after 5 seconds, and then stops the event loop::
|
|
|
|
import asyncio
|
|
import datetime
|
|
|
|
def display_date(end_time, loop):
|
|
print(datetime.datetime.now())
|
|
if (loop.time() + 1.0) < end_time:
|
|
loop.call_later(1, display_date, end_time, loop)
|
|
else:
|
|
loop.stop()
|
|
|
|
loop = asyncio.new_event_loop()
|
|
|
|
# Schedule the first call to display_date()
|
|
end_time = loop.time() + 5.0
|
|
loop.call_soon(display_date, end_time, loop)
|
|
|
|
# Blocking call interrupted by loop.stop()
|
|
try:
|
|
loop.run_forever()
|
|
finally:
|
|
loop.close()
|
|
|
|
.. seealso::
|
|
|
|
A similar :ref:`current date <asyncio_example_sleep>` example
|
|
created with a coroutine and the :func:`run` function.
|
|
|
|
|
|
.. _asyncio_example_watch_fd:
|
|
|
|
Watch a file descriptor for read events
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Wait until a file descriptor received some data using the
|
|
:meth:`loop.add_reader` method and then close the event loop::
|
|
|
|
import asyncio
|
|
from socket import socketpair
|
|
|
|
# Create a pair of connected file descriptors
|
|
rsock, wsock = socketpair()
|
|
|
|
loop = asyncio.new_event_loop()
|
|
|
|
def reader():
|
|
data = rsock.recv(100)
|
|
print("Received:", data.decode())
|
|
|
|
# We are done: unregister the file descriptor
|
|
loop.remove_reader(rsock)
|
|
|
|
# Stop the event loop
|
|
loop.stop()
|
|
|
|
# Register the file descriptor for read event
|
|
loop.add_reader(rsock, reader)
|
|
|
|
# Simulate the reception of data from the network
|
|
loop.call_soon(wsock.send, 'abc'.encode())
|
|
|
|
try:
|
|
# Run the event loop
|
|
loop.run_forever()
|
|
finally:
|
|
# We are done. Close sockets and the event loop.
|
|
rsock.close()
|
|
wsock.close()
|
|
loop.close()
|
|
|
|
.. seealso::
|
|
|
|
* A similar :ref:`example <asyncio_example_create_connection>`
|
|
using transports, protocols, and the
|
|
:meth:`loop.create_connection` method.
|
|
|
|
* Another similar :ref:`example <asyncio_example_create_connection-streams>`
|
|
using the high-level :func:`asyncio.open_connection` function
|
|
and streams.
|
|
|
|
|
|
.. _asyncio_example_unix_signals:
|
|
|
|
Set signal handlers for SIGINT and SIGTERM
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
(This ``signals`` example only works on Unix.)
|
|
|
|
Register handlers for signals :const:`~signal.SIGINT` and :const:`~signal.SIGTERM`
|
|
using the :meth:`loop.add_signal_handler` method::
|
|
|
|
import asyncio
|
|
import functools
|
|
import os
|
|
import signal
|
|
|
|
def ask_exit(signame, loop):
|
|
print("got signal %s: exit" % signame)
|
|
loop.stop()
|
|
|
|
async def main():
|
|
loop = asyncio.get_running_loop()
|
|
|
|
for signame in {'SIGINT', 'SIGTERM'}:
|
|
loop.add_signal_handler(
|
|
getattr(signal, signame),
|
|
functools.partial(ask_exit, signame, loop))
|
|
|
|
await asyncio.sleep(3600)
|
|
|
|
print("Event loop running for 1 hour, press Ctrl+C to interrupt.")
|
|
print(f"pid {os.getpid()}: send SIGINT or SIGTERM to exit.")
|
|
|
|
asyncio.run(main())
|