Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Edit README to assume less background knowledge #26

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 44 additions & 12 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,44 @@
The async_generator library
===========================

Python 3.6 added `async generators
<https://www.python.org/dev/peps/pep-0525/>`__. (What's an async
generator? `Check out my 5-minute lightning talk demo from PyCon 2016
<https://youtu.be/PulzIT8KYLk?t=24m30s>`__.) Python 3.7 adds some more
tools to make them usable, like ``contextlib.asynccontextmanager``.
Many Python programmers already know and love `generators
<https://medium.freecodecamp.org/how-and-why-you-should-use-python-generators-f6fb56650888>`__,
because they're a super convenient way to write your own iterators
that you can loop over using ``for``. Python 3.6 added a new thing:
`async generators <https://www.python.org/dev/peps/pep-0525/>`__. Just
like regular generators, they're super convenient; the difference is
that now you loop over them using ``async for``, and this means you
can use ``await`` inside them. If you're not doing async programming,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm worried this might not help the confusion between regular iterators, regular generators, async iterators (as introduced in 3.5 / PEP 492) and async generators (as introduced in 3.6 / PEP 525). This is not the place to go that deep in explanations. But since you're already giving pointers, it might be helpful to clarify that—just like generators are a nice way to write iterators—async generators are super useful to define async iterators.

you probably don't care about this at all. But if you *are* doing
async programming, this is *super awesome*. If you're not convinced,
check out this `5-minute demo
<https://youtu.be/PulzIT8KYLk?t=24m30s>`__ (warning: contains
Nathaniel's first ever attempt to live-code on stage).

But what if you aren't using the latest and greatest Python, but still
want that async generator goodness? That's where this package comes
in. It gives you async generators and ``@asynccontextmanager`` on
Python 3.5+.

**Example 1:** suppose you want to **write your own async generator**.
The goal is that you can use it like:

This library gives you all that back to Python 3.5.
.. code-block:: python3

async for json_obj in load_json_lines(stream_reader):
...

For example, this code only works in Python 3.6+:
If you're using Python 3.6+, you could implement `load_json_lines`
using native syntax:

.. code-block:: python3

async def load_json_lines(stream_reader):
async for line in stream_reader:
yield json.loads(line)

But this code does the same thing, and works on Python 3.5+:
Or, you could use ``async_generator``, and now your code will work on
Python 3.5+:

.. code-block:: python3

Expand All @@ -48,7 +69,17 @@ But this code does the same thing, and works on Python 3.5+:
async for line in stream_reader:
await yield_(json.loads(line))

Or in Python 3.7, you can write:

**Example 2:** let's say you want to **write your own async context
manager**. The goal is to be able to write:

.. code-block:: python3

async with background_server() as ...:
...

If you're using Python 3.7+, you don't need this library; you can
write something like:

.. code-block:: python3

Expand All @@ -64,7 +95,7 @@ Or in Python 3.7, you can write:
# Kill the server when the scope exits
nursery.cancel_scope.cancel()

This is the same, but back to 3.5:
This is the same, but works on 3.5+:

.. code-block:: python3

Expand All @@ -81,8 +112,9 @@ This is the same, but back to 3.5:
# Kill the server when the scope exits
nursery.cancel_scope.cancel()

(And if you're on 3.6, you can use ``@asynccontextmanager`` with
native generators.)
(And if you're on 3.6, so you have built-in async generators but no
built-in ``@asynccontextmanager``, then don't worry, you can use
``async_generator.asynccontextmanager`` on native async generators.)


Let's do this
Expand Down