Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0366004

Browse files
committed
Issue #28091: Document PEP 525 & PEP 530.
Patch by Eric Appelt.
1 parent 76febd0 commit 0366004

9 files changed

Lines changed: 298 additions & 4 deletions

File tree

Doc/glossary.rst

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,34 @@ Glossary
7474
:keyword:`async with` statement by defining :meth:`__aenter__` and
7575
:meth:`__aexit__` methods. Introduced by :pep:`492`.
7676

77+
asynchronous generator
78+
A function which returns an :term:`asynchronous generator iterator`. It
79+
looks like a coroutine function defined with :keyword:`async def` except
80+
that it contains :keyword:`yield` expressions for producing a series of
81+
values usable in an :keyword:`async for` loop.
82+
83+
Usually refers to a asynchronous generator function, but may refer to an
84+
*asynchronous generator iterator* in some contexts. In cases where the
85+
intended meaning isn't clear, using the full terms avoids ambiguity.
86+
87+
An asynchronous generator function may contain :keyword:`await`
88+
expressions as well as :keyword:`async for`, and :keyword:`async with`
89+
statements.
90+
91+
asynchronous generator iterator
92+
An object created by a :term:`asynchronous generator` function.
93+
94+
This is an :term:`asynchronous iterator` which when called using the
95+
:meth:`__anext__` method returns an awaitable object which will execute
96+
that the body of the asynchronous generator function until the
97+
next :keyword:`yield` expression.
98+
99+
Each :keyword:`yield` temporarily suspends processing, remembering the
100+
location execution state (including local variables and pending
101+
try-statements). When the *asynchronous generator iterator* effectively
102+
resumes with another awaitable returned by :meth:`__anext__`, it
103+
picks-up where it left-off. See :pep:`492` and :pep:`525`.
104+
77105
asynchronous iterable
78106
An object, that can be used in an :keyword:`async for` statement.
79107
Must return an :term:`asynchronous iterator` from its

Doc/library/asyncio-eventloop.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,24 @@ Run an event loop
8888
This is idempotent and irreversible. No other methods should be called after
8989
this one.
9090

91+
92+
.. coroutinemethod:: AbstractEventLoop.shutdown_asyncgens()
93+
94+
Schedule all currently open :term:`asynchronous generator` objects to
95+
close with an :meth:`~agen.aclose()` call. After calling this method,
96+
the event loop will issue a warning whenever a new asynchronous generator
97+
is iterated. Should be used to finalize all scheduled asynchronous
98+
generators reliably. Example::
99+
100+
try:
101+
loop.run_forever()
102+
finally:
103+
loop.run_until_complete(loop.shutdown_asyncgens())
104+
loop.close()
105+
106+
.. versionadded:: 3.6
107+
108+
91109
.. _asyncio-pass-keywords:
92110

93111
Calls

Doc/library/inspect.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,27 @@ attributes:
318318
.. versionadded:: 3.5
319319

320320

321+
.. function:: isasyncgenfunction(object)
322+
323+
Return true if the object is an :term:`asynchronous generator` function,
324+
for example::
325+
326+
>>> async def agen():
327+
... yield 1
328+
...
329+
>>> inspect.isasyncgenfunction(agen)
330+
True
331+
332+
.. versionadded:: 3.6
333+
334+
335+
.. function:: isasyncgen(object)
336+
337+
Return true if the object is an :term:`asynchronous generator iterator`
338+
created by an :term:`asynchronous generator` function.
339+
340+
.. versionadded:: 3.6
341+
321342
.. function:: istraceback(object)
322343

323344
Return true if the object is a traceback.

Doc/library/sys.rst

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,24 @@ always available.
594594
.. versionchanged:: 3.6
595595
Added *platform_version*
596596

597+
598+
.. function:: get_asyncgen_hooks()
599+
600+
Returns an *asyncgen_hooks* object, which is similar to a
601+
:class:`~collections.namedtuple` of the form `(firstiter, finalizer)`,
602+
where *firstiter* and *finalizer* are expected to be either ``None`` or
603+
functions which take an :term:`asynchronous generator iterator` as an
604+
argument, and are used to schedule finalization of an asychronous
605+
generator by an event loop.
606+
607+
.. versionadded:: 3.6
608+
See :pep:`525` for more details.
609+
610+
.. note::
611+
This function has been added on a provisional basis (see :pep:`411`
612+
for details.)
613+
614+
597615
.. function:: get_coroutine_wrapper()
598616

599617
Returns ``None``, or a wrapper set by :func:`set_coroutine_wrapper`.
@@ -1098,6 +1116,24 @@ always available.
10981116
implementation platform, rather than part of the language definition, and
10991117
thus may not be available in all Python implementations.
11001118

1119+
.. function:: set_asyncgen_hooks(firstiter, finalizer)
1120+
1121+
Accepts two optional keyword arguments which are callables that accept an
1122+
:term:`asynchronous generator iterator` as an argument. The *firstiter*
1123+
callable will be called when an asynchronous generator is iterated for the
1124+
first time. The *finalizer* will be called when an asynchronous generator
1125+
is about to be garbage collected.
1126+
1127+
.. versionadded:: 3.6
1128+
See :pep:`525` for more details, and for a reference example of a
1129+
*finalizer* method see the implementation of
1130+
``asyncio.Loop.shutdown_asyncgens`` in
1131+
:source:`Lib/asyncio/base_events.py`
1132+
1133+
.. note::
1134+
This function has been added on a provisional basis (see :pep:`411`
1135+
for details.)
1136+
11011137

11021138
.. function:: set_coroutine_wrapper(wrapper)
11031139

Doc/library/types.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,14 @@ Standard names are defined for the following types:
104104
.. versionadded:: 3.5
105105

106106

107+
.. data:: AsyncGeneratorType
108+
109+
The type of :term:`asynchronous generator`-iterator objects, created by
110+
asynchronous generator functions.
111+
112+
.. versionadded:: 3.6
113+
114+
107115
.. data:: CodeType
108116

109117
.. index:: builtin: compile

Doc/reference/compound_stmts.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ coroutine bodies.
697697
Functions defined with ``async def`` syntax are always coroutine functions,
698698
even if they do not contain ``await`` or ``async`` keywords.
699699

700-
It is a :exc:`SyntaxError` to use :keyword:`yield` expressions in
700+
It is a :exc:`SyntaxError` to use ``yield from`` expressions in
701701
``async def`` coroutines.
702702

703703
An example of a coroutine function::

Doc/reference/datamodel.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,25 @@ Callable types
627627
as well as :keyword:`async with` and :keyword:`async for` statements. See
628628
also the :ref:`coroutine-objects` section.
629629

630+
Asynchronous generator functions
631+
.. index::
632+
single: asynchronous generator; function
633+
single: asynchronous generator; asynchronous iterator
634+
635+
A function or method which is defined using :keyword:`async def` and
636+
which uses the :keyword:`yield` statement is called a
637+
:dfn:`asynchronous generator function`. Such a function, when called,
638+
returns an asynchronous iterator object which can be used in an
639+
:keyword:`async for` statement to execute the body of the function.
640+
641+
Calling the asynchronous iterator's :meth:`aiterator.__anext__` method
642+
will return an :term:`awaitable` which when awaited
643+
will execute until it provides a value using the :keyword:`yield`
644+
expression. When the function executes an empty :keyword:`return`
645+
statement or falls off the end, a :exc:`StopAsyncIteration` exception
646+
is raised and the asynchronous iterator will have reached the end of
647+
the set of values to be yielded.
648+
630649
Built-in functions
631650
.. index::
632651
object: built-in function

Doc/reference/expressions.rst

Lines changed: 163 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ Common syntax elements for comprehensions are:
172172

173173
.. productionlist::
174174
comprehension: `expression` `comp_for`
175-
comp_for: "for" `target_list` "in" `or_test` [`comp_iter`]
175+
comp_for: [ASYNC] "for" `target_list` "in" `or_test` [`comp_iter`]
176176
comp_iter: `comp_for` | `comp_if`
177177
comp_if: "if" `expression_nocond` [`comp_iter`]
178178

@@ -186,6 +186,17 @@ each time the innermost block is reached.
186186
Note that the comprehension is executed in a separate scope, so names assigned
187187
to in the target list don't "leak" into the enclosing scope.
188188

189+
Since Python 3.6, in an :keyword:`async def` function, an :keyword:`async for`
190+
clause may be used to iterate over a :term:`asynchronous iterator`.
191+
A comprehension in an :keyword:`async def` function may consist of either a
192+
:keyword:`for` or :keyword:`async for` clause following the leading
193+
expression, may contan additonal :keyword:`for` or :keyword:`async for`
194+
clauses, and may also use :keyword:`await` expressions.
195+
If a comprehension contains either :keyword:`async for` clauses
196+
or :keyword:`await` expressions it is called an
197+
:dfn:`asynchronous comprehension`. An asynchronous comprehension may
198+
suspend the execution of the coroutine function in which it appears.
199+
See also :pep:`530`.
189200

190201
.. _lists:
191202

@@ -315,6 +326,14 @@ range(10) for y in bar(x))``.
315326
The parentheses can be omitted on calls with only one argument. See section
316327
:ref:`calls` for details.
317328

329+
Since Python 3.6, if the generator appears in an :keyword:`async def` function,
330+
then :keyword:`async for` clauses and :keyword:`await` expressions are permitted
331+
as with an asynchronous comprehension. If a generator expression
332+
contains either :keyword:`async for` clauses or :keyword:`await` expressions
333+
it is called an :dfn:`asynchronous generator expression`.
334+
An asynchronous generator expression yields a new asynchronous
335+
generator object, which is an asynchronous iterator
336+
(see :ref:`async-iterators`).
318337

319338
.. _yieldexpr:
320339

@@ -330,9 +349,22 @@ Yield expressions
330349
yield_atom: "(" `yield_expression` ")"
331350
yield_expression: "yield" [`expression_list` | "from" `expression`]
332351

333-
The yield expression is only used when defining a :term:`generator` function and
352+
The yield expression is used when defining a :term:`generator` function
353+
or an :term:`asynchronous generator` function and
334354
thus can only be used in the body of a function definition. Using a yield
335-
expression in a function's body causes that function to be a generator.
355+
expression in a function's body causes that function to be a generator,
356+
and using it in an :keyword:`async def` function's body causes that
357+
coroutine function to be an asynchronous generator. For example::
358+
359+
def gen(): # defines a generator function
360+
yield 123
361+
362+
async def agen(): # defines an asynchronous generator function (PEP 525)
363+
yield 123
364+
365+
Generator functions are described below, while asynchronous generator
366+
functions are described separately in section
367+
:ref:`asynchronous-generator-functions`.
336368

337369
When a generator function is called, it returns an iterator known as a
338370
generator. That generator then controls the execution of the generator function.
@@ -496,6 +528,134 @@ generator functions::
496528
For examples using ``yield from``, see :ref:`pep-380` in "What's New in
497529
Python."
498530

531+
.. _asynchronous-generator-functions:
532+
533+
Asynchronous generator functions
534+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
535+
536+
The presence of a yield expression in a function or method defined using
537+
:keyword:`async def` further defines the function as a
538+
:term:`asynchronous generator` function.
539+
540+
When an asynchronous generator function is called, it returns an
541+
asynchronous iterator known as an asynchronous generator object.
542+
That object then controls the execution of the generator function.
543+
An asynchronous generator object is typically used in an
544+
:keyword:`async for` statement in a coroutine function analogously to
545+
how a generator object would be used in a :keyword:`for` statement.
546+
547+
Calling one of the asynchronous generator's methods returns an
548+
:term:`awaitable` object, and the execution starts when this object
549+
is awaited on. At that time, the execution proceeds to the first yield
550+
expression, where it is suspended again, returning the value of
551+
:token:`expression_list` to the awaiting coroutine. As with a generator,
552+
suspension means that all local state is retained, including the
553+
current bindings of local variables, the instruction pointer, the internal
554+
evaluation stack, and the state of any exception handling. When the execution
555+
is resumed by awaiting on the next object returned by the asynchronous
556+
generator's methods, the function can proceed exactly as if the yield
557+
expression were just another external call. The value of the yield expression
558+
after resuming depends on the method which resumed the execution. If
559+
:meth:`~agen.__anext__` is used then the result is :const:`None`. Otherwise, if
560+
:meth:`~agen.asend` is used, then the result will be the value passed in to
561+
that method.
562+
563+
In an asynchronous generator function, yield expressions are allowed anywhere
564+
in a :keyword:`try` construct. However, if an asynchronous generator is not
565+
resumed before it is finalized (by reaching a zero reference count or by
566+
being garbage collected), then a yield expression within a :keyword:`try`
567+
construct could result in a failure to execute pending :keyword:`finally`
568+
clauses. In this case, it is the responsibility of the event loop or
569+
scheduler running the asynchronous generator to call the asynchronous
570+
generator-iterator's :meth:`~agen.aclose` method and run the resulting
571+
coroutine object, thus allowing any pending :keyword:`finally` clauses
572+
to execute.
573+
574+
To take care of finalization, an event loop should define
575+
a *finalizer* function which takes an asynchronous generator-iterator
576+
and presumably calls :meth:`~agen.aclose` and executes the coroutine.
577+
This *finalizer* may be registered by calling :func:`sys.set_asyncgen_hooks`.
578+
When first iterated over, an asynchronous generator-iterator will store the
579+
registered *finalizer* to be called upon finalization. For a reference example
580+
of a *finalizer* method see the implementation of
581+
``asyncio.Loop.shutdown_asyncgens`` in :source:`Lib/asyncio/base_events.py`.
582+
583+
The expression ``yield from <expr>`` is a syntax error when used in an
584+
asynchronous generator function.
585+
586+
.. index:: object: asynchronous-generator
587+
.. _asynchronous-generator-methods:
588+
589+
Asynchronous generator-iterator methods
590+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
591+
592+
This subsection describes the methods of an asynchronous generator iterator,
593+
which are used to control the execution of a generator function.
594+
595+
596+
.. index:: exception: StopAsyncIteration
597+
598+
.. coroutinemethod:: agen.__anext__()
599+
600+
Returns an awaitable which when run starts to execute the asynchronous
601+
generator or resumes it at the last executed yield expression. When an
602+
asynchronous generator function is resumed with a :meth:`~agen.__anext__`
603+
method, the current yield expression always evaluates to :const:`None` in
604+
the returned awaitable, which when run will continue to the next yield
605+
expression. The value of the :token:`expression_list` of the yield
606+
expression is the value of the :exc:`StopIteration` exception raised by
607+
the completing coroutine. If the asynchronous generator exits without
608+
yielding another value, the awaitable instead raises an
609+
:exc:`StopAsyncIteration` exception, signalling that the asynchronous
610+
iteration has completed.
611+
612+
This method is normally called implicitly by a :keyword:`async for` loop.
613+
614+
615+
.. coroutinemethod:: agen.asend(value)
616+
617+
Returns an awaitable which when run resumes the execution of the
618+
asynchronous generator. As with the :meth:`~generator.send()` method for a
619+
generator, this "sends" a value into the asynchronous generator function,
620+
and the *value* argument becomes the result of the current yield expression.
621+
The awaitable returned by the :meth:`asend` method will return the next
622+
value yielded by the generator as the value of the raised
623+
:exc:`StopIteration`, or raises :exc:`StopAsyncIteration` if the
624+
asynchronous generator exits without yielding another value. When
625+
:meth:`asend` is called to start the asynchronous
626+
generator, it must be called with :const:`None` as the argument,
627+
because there is no yield expression that could receive the value.
628+
629+
630+
.. coroutinemethod:: agen.athrow(type[, value[, traceback]])
631+
632+
Returns an awaitable that raises an exception of type ``type`` at the point
633+
where the asynchronous generator was paused, and returns the next value
634+
yielded by the generator function as the value of the raised
635+
:exc:`StopIteration` exception. If the asynchronous generator exits
636+
without yielding another value, an :exc:`StopAsyncIteration` exception is
637+
raised by the awaitable.
638+
If the generator function does not catch the passed-in exception, or
639+
raises a different exception, then when the awaitalbe is run that exception
640+
propagates to the caller of the awaitable.
641+
642+
.. index:: exception: GeneratorExit
643+
644+
645+
.. coroutinemethod:: agen.aclose()
646+
647+
Returns an awaitable that when run will throw a :exc:`GeneratorExit` into
648+
the asynchronous generator function at the point where it was paused.
649+
If the asynchronous generator function then exits gracefully, is already
650+
closed, or raises :exc:`GeneratorExit` (by not catching the exception),
651+
then the returned awaitable will raise a :exc:`StopIteration` exception.
652+
Any further awaitables returned by subsequent calls to the asynchronous
653+
generator will raise a :exc:`StopAsyncIteration` exception. If the
654+
asynchronous generator yields a value, a :exc:`RuntimeError` is raised
655+
by the awaitable. If the asynchronous generator raises any other exception,
656+
it is propagated to the caller of the awaitable. If the asynchronous
657+
generator has already exited due to an exception or normal exit, then
658+
further calls to :meth:`aclose` will return an awaitable that does nothing.
499659

500660
.. _primaries:
501661

0 commit comments

Comments
 (0)