[Python-checkins] peps: Refactor run*() family, rename Handler->Handle, updated intros.

guido.van.rossum python-checkins at python.org
Sun Mar 24 21:35:13 CET 2013


http://hg.python.org/peps/rev/26a98d94bb4c
changeset: 4820:26a98d94bb4c
user: Guido van Rossum <guido at python.org>
date: Sun Mar 24 13:34:39 2013 -0700
summary:
 Refactor run*() family, rename Handler->Handle, updated intros.
files:
 pep-3156.txt | 145 ++++++++++++++++----------------------
 1 files changed, 61 insertions(+), 84 deletions(-)
diff --git a/pep-3156.txt b/pep-3156.txt
--- a/pep-3156.txt
+++ b/pep-3156.txt
@@ -17,8 +17,8 @@
 PEP 3153. The proposal includes a pluggable event loop API, transport
 and protocol abstractions similar to those in Twisted, and a
 higher-level scheduler based on ``yield from`` (PEP 380). A reference
-implementation is in the works under the code name Tulip (the Tulip
-repo is linked from the References section at the end).
+implementation is in the works under the code name Tulip. The Tulip
+repo is linked from the References section at the end.
 
 
 Introduction
@@ -26,24 +26,33 @@
 
 The event loop is the place where most interoperability occurs. It
 should be easy for (Python 3.3 ports of) frameworks like Twisted,
-Tornado, or ZeroMQ to either adapt the default event loop
+Tornado, or even gevents to either adapt the default event loop
 implementation to their needs using a lightweight wrapper or proxy, or
 to replace the default event loop implementation with an adaptation of
 their own event loop implementation. (Some frameworks, like Twisted,
 have multiple event loop implementations. This should not be a
 problem since these all have the same interface.)
 
-It should even be possible for two different third-party frameworks to
-interoperate, either by sharing the default event loop implementation
-(each using its own adapter), or by sharing the event loop
-implementation of either framework. In the latter case two levels of
-adaptation would occur (from framework A's event loop to the standard
-event loop interface, and from there to framework B's event loop).
-Which event loop implementation is used should be under control of the
-main program (though a default policy for event loop selection is
-provided).
+In most cases it should be possible for two different third-party
+frameworks to interoperate, either by sharing the default event loop
+implementation (each using its own adapter), or by sharing the event
+loop implementation of either framework. In the latter case two
+levels of adaptation would occur (from framework A's event loop to the
+standard event loop interface, and from there to framework B's event
+loop). Which event loop implementation is used should be under
+control of the main program (though a default policy for event loop
+selection is provided).
 
-Thus, two separate APIs are defined:
+For this interoperability to be effective, the preferred direction of
+adaptation in third party frameworks is to keep the default event loop
+and adapt it to the framework's API. Ideally all third party
+frameworks would give up their own event loop implementation in favor
+of the standard implementation. But not all frameworks may be
+satisfied with the functionality provided by the standard
+implementation.
+
+In order to support both directions of adaptation, two separate APIs
+are defined:
 
 - getting and setting the current event loop object
 - the interface of a conforming event loop and its minimum guarantees
@@ -118,13 +127,6 @@
 later.
 
 
-Non-goals
-=========
-
-Interoperability with systems like Stackless Python or
-greenlets/gevent is not a goal of this PEP.
-
-
 Specification
 =============
 
@@ -195,35 +197,18 @@
 accuracy and precision of the clock are up to the implementation; the
 default implementation uses ``time.monotonic()``.
 
-A note about callbacks and Handlers: any function that takes a
+A note about callbacks and Handles: any function that takes a
 callback and a variable number of arguments for it can also be given a
-Handler object instead of the callback. Then no arguments should be
-given, and the Handler should represent an immediate callback (as
+Handle object instead of the callback. Then no arguments should be
+given, and the Handle should represent an immediate callback (as
 returned from ``call_soon()``), not a delayed callback (as returned
-from ``call_later()``). If the Handler is already cancelled, the
+from ``call_later()``). If the Handle is already cancelled, the
 call is a no-op.
 
 A conforming event loop object has the following methods:
 
-- ``run()``. Runs the event loop until there is nothing left to do.
- This means, in particular:
-
- - No more calls scheduled with ``call_later()``,
- ``call_repeatedly()``, ``call_soon()``, or
- ``call_soon_threadsafe()``, except for cancelled calls.
-
- - No more registered file descriptors. It is up to the registering
- party to unregister a file descriptor when it is closed.
-
- Note: ``run()`` blocks until the termination condition is met,
- or until ``stop()`` is called.
-
- Note: if you schedule a call with ``call_repeatedly()``, ``run()``
- will not exit until you cancel it.
-
- TBD: How many variants of this do we really need?
-
-- ``run_forever()``. Runs the event loop until ``stop()`` is called.
+- ``run()``. Runs the event loop until ``stop()`` is called. This
+ cannot be called when the event loop is already running.
 
 - ``run_until_complete(future, timeout=None)``. Runs the event loop
 until the Future is done. If a timeout is given, it waits at most
@@ -232,28 +217,12 @@
 done, or if ``stop()`` is called, ``TimeoutError`` is raised (but
 the Future is not cancelled). This cannot be called when the event
 loop is already running.
- 
- Note: This API is most useful for tests and the like. It should not
- be used as a substitute for ``yield from future`` or other ways to
- wait for a Future (e.g. registering a done callback).
-
-- ``run_once(timeout=None)``. Run the event loop for a little while.
- If a timeout is given, an I/O poll made will block at most that
- long; otherwise, an I/O poll is not constrained in time.
-
- Note: Exactlly how much work this does is up to the implementation.
- One constraint: if a callback immediately schedules itself using
- ``call_soon()``, causing an infinite loop, ``run_once()`` should
- still return.
 
 - ``stop()``. Stops the event loop as soon as it is convenient. It
- is fine to restart the loop with ``run()`` (or one of its variants)
- subsequently.
+ is fine to restart the loop with ``run()`` or ``run_until_complete()``
+ subsequently; no scheduled callbacks will be lost if this happens.
 
- Note: How soon exactly is up to the implementation. All immediate
- callbacks that were already scheduled to run before ``stop()`` is
- called must still be run, but callbacks scheduled after it is called
- (or scheduled to be run later) will not be run.
+ Note: How soon the event loop stops is up to the implementation.
 
 - ``close()``. Closes the event loop, releasing any resources it may
 hold, such as the file descriptor used by ``epoll()`` or
@@ -263,16 +232,23 @@
 - ``call_later(delay, callback, *args)``. Arrange for
 ``callback(*args)`` to be called approximately ``delay`` seconds in
 the future, once, unless cancelled. Returns
- a ``Handler`` object representing the callback, whose
+ a ``Handle`` object representing the callback, whose
 ``cancel()`` method can be used to cancel the callback.
+ If ``delay`` is <= 0, this acts like ``call_soon()`` instead.
+ Otherwise, callbacks scheduled for exactly the same time will be
+ called in an undefined order.
 
-- ``call_repeatedly(interval, callback, **args)``. Like ``call_later()``
- but calls the callback repeatedly, every ``interval`` seconds,
- until the ``Handler`` returned is cancelled. The first call is in
- ``interval`` seconds.
+- ``call_repeatedly(interval, callback, **args)``. Like
+ ``call_later()`` but calls the callback repeatedly, every (approximately) 
+ ``interval`` seconds, until the ``Handle`` returned is cancelled or
+ the callback raises an exception. The first call is in
+ approximately ``interval`` seconds. If for whatever reason the
+ callback happens later than scheduled, subsequent callbacks will be
+ delayed for (at least) the same amount. The ``interval`` must be > 0.
 
-- ``call_soon(callback, *args)``. Equivalent to ``call_later(0,
- callback, *args)``.
+- ``call_soon(callback, *args)``. This schedules a callback to be
+ called as soon as possible. It guarantees that callbacks are called
+ in the order in which they were scheduled.
 
 - ``call_soon_threadsafe(callback, *args)``. Like
 ``call_soon(callback, *args)``, but when called from another thread
@@ -286,8 +262,8 @@
 
 - ``add_signal_handler(sig, callback, *args). Whenever signal ``sig``
 is received, arrange for ``callback(*args)`` to be called. Returns
- a ``Handler`` which can be used to cancel the signal callback.
- (Cancelling the handler causes ``remove_signal_handler()`` to be
+ a ``Handle`` which can be used to cancel the signal callback.
+ (Cancelling the handle causes ``remove_signal_handler()`` to be
 called the next time the signal arrives. Explicitly calling
 ``remove_signal_handler()`` is preferred.)
 Specifying another callback for the same signal replaces the
@@ -298,13 +274,13 @@
 signale (e.g. ``SIGKILL``), ``RuntimeError`` if this particular event
 loop instance cannot handle signals (since signals are global per
 process, only an event loop associated with the main thread can
- handle signals).
+ handle signals). (TBD: Rename to ``set_signal_handler()``?)
 
 - ``remove_signal_handler(sig)``. Removes the handler for signal
 ``sig``, if one is set. Raises the same exceptions as
 ``add_signal_handler()`` (except that it may return ``False``
 instead raising ``RuntimeError`` for uncatchable signals). Returns
- ``True``e\ if a handler was removed successfully, ``False`` if no
+ ``True`` if a handler was removed successfully, ``False`` if no
 handler was set.
 
 Some methods in the standard conforming interface return Futures:
@@ -417,25 +393,26 @@
 
 - ``add_reader(fd, callback, *args)``. Arrange for
 ``callback(*args)`` to be called whenever file descriptor ``fd`` is
- ready for reading. Returns a ``Handler`` object which can be
+ ready for reading. Returns a ``Handle`` object which can be
 used to cancel the callback. Note that, unlike ``call_later()``,
 the callback may be called many times. Calling ``add_reader()``
 again for the same file descriptor implicitly cancels the previous
- callback for that file descriptor. Note: cancelling the handler
- may be delayed until the handler would be called. If you plan to
+ callback for that file descriptor. Note: cancelling the handle
+ may be delayed until the handle would be called. If you plan to
 close ``fd``, you should use ``remove_reader(fd)`` instead.
- (TBD: Change this to raise an exception if a handler
- is already set.)
+ (TBD: Change this to raise an exception if a handle
+ is already set.) (TBD: Rename to ``set_reader()``?)
 
 - ``add_writer(fd, callback, *args)``. Like ``add_reader()``,
 but registers the callback for writing instead of for reading.
+ (TBD: Rename to ``set_reader()``?)
 
 - ``remove_reader(fd)``. Cancels the current read callback for file
 descriptor ``fd``, if one is set. A no-op if no callback is
 currently set for the file descriptor. (The reason for providing
 this alternate interface is that it is often more convenient to
- remember the file descriptor than to remember the ``Handler``
- object.) Returns ``True`` if a handler was removed, ``False``
+ remember the file descriptor than to remember the ``Handle``
+ object.) Returns ``True`` if a callback was removed, ``False``
 if not.
 
 - ``remove_writer(fd)``. This is to ``add_writer()`` as
@@ -522,13 +499,13 @@
 and ``SystemExit``; it is usually unwise to treat these the same as
 most other exceptions.)
 
-The Handler Class
------------------
+The Handle Class
+----------------
 
 The various methods for registering callbacks (e.g. ``call_later()``)
 all return an object representing the registration that can be used to
 cancel the callback. For want of a better name this object is called
-a ``Handler``, although the user never needs to instantiate
+a ``Handle``, although the user never needs to instantiate
 instances of this class. There is one public method:
 
 - ``cancel()``. Attempt to cancel the callback.
@@ -597,7 +574,7 @@
 ``call_soon()``. Note that the callback (unlike all other callbacks
 defined in this PEP, and ignoring the convention from the section
 "Callback Style" below) is always called with a single argument, the
- Future object, and should not be a Handler object.
+ Future object, and should not be a Handle object.
 
 - ``set_result(result)``. The Future must not be done (nor cancelled)
 already. This makes the Future done and schedules the callbacks.
-- 
Repository URL: http://hg.python.org/peps


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /