# aiochannel - AsyncIO Channel
[![Build Status](https://github.com/tbug/aiochannel/actions/workflows/test.yml/badge.svg)][Build Status]
[![Stable Version](https://img.shields.io/pypi/v/aiochannel?label=stable)][PyPI Releases]
[![Python Versions](https://img.shields.io/pypi/pyversions/aiochannel)][PyPI]
[![Download Stats](https://img.shields.io/pypi/dm/aiochannel)](https://pypistats.org/packages/aiochannel)
Channel concept for asyncio.
## Install
```
pip install aiochannel
```
## Changelog
[Changelog]
## Usage
### Basics
`Channel` has a very similar API to `asyncio.Queue`.
The key difference is that a channel is only considered
"done" when it has been both closed and drained, so calling `.join()`
on a channel will wait for it to be both closed and drained (Unlike
`Queue` which will return from `.join()` once the queue is empty).
**NOTE:** Closing a channel is permanent. You cannot open it again.
```python
import asyncio
from aiochannel import Channel
# ...
async def main():
# A Channel takes a max queue size and an loop
# both optional. loop is not recommended as
# in asyncio is phasing out explicitly passed event-loop
my_channel: Channel[str] = Channel(100)
# You add items to the channel with
await my_channel.put("my item")
# Note that this can throw ChannelClosed if the channel
# is closed, during the attempt at adding the item
# to the channel. Also note that .put() will block until
# it can successfully add the item.
# Retrieving is done with
my_item = await my_channel.get()
# Note that this can also throw ChannelClosed if the
# channel is closed before or during retrival.
# .get() will block until an item can be retrieved.
# Note that this requires someone else to close and drain
# the channel.
# Lastly, you can close a channel with `my_channel.close()`
# In this example, the event-loop call this asynchronously
asyncio.get_event_loop().call_later(0.1, my_channel.close)
# You can wait for the channel to be closed and drained:
await my_channel.join()
# Every call to .put() after .close() will fail with
# a ChannelClosed.
# you can check if a channel is marked for closing with
if my_channel.closed():
print ("Channel is closed")
asyncio.run(main())
```
Like the `asyncio.Queue` you can also call non-async get and put:
<!--pytest.mark.skip-->
```python
# non-async version of put
my_channel.put_nowait(item)
# This either returns None,
# or raises ChannelClosed or ChannelFull
# non-async version of get
my_channel.get_nowait()
# This either returns the next item from the channel
# or raises ChannelEmpty or ChannelClosed
# (Note that ChannelClosed emplies that the channel
# is empty, but also that is will never fill again)
```
As of `0.2.0` `Channel` also implements the async iterator protocol.
You can now use `async for` to iterate over the channel until it
closes, without having to deal with `ChannelClosed` exceptions.
<!--pytest.mark.skip-->
```python
# the channel might contain data here
async for item in channel:
print(item)
# the channel is closed and empty here
```
which is functionally equivalent to
<!--pytest.mark.skip-->
```python
while True:
try:
data = yield from channel.get()
except ChannelClosed:
break
# process data here
```
[PyPI]: https://pypi.org/project/aiochannel
[PyPI Releases]: https://pypi.org/project/aiochannel/#history
[Github]: https://github.com/tbug/aiochannel
[Changelog]: https://github.com/tbug/aiochannel/blob/master/CHANGELOG.md
[Issue Tracker]: https://github.com/tbug/aiochannel/issues
[Build Status]: https://github.com/tbug/aiochannel/actions/workflows/test.yml
Raw data
{
"_id": null,
"home_page": "https://github.com/tbug/aiochannel",
"name": "aiochannel",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.9",
"maintainer_email": null,
"keywords": "asyncio, aio, chan, channel, gochan",
"author": "Henrik Tudborg",
"author_email": "henrik@tudb.org",
"download_url": "https://files.pythonhosted.org/packages/3f/a2/94d9fe4436bab8238120ff07b78043e9e4029fb1a102791c7a0b4475b6cb/aiochannel-1.3.0.tar.gz",
"platform": null,
"description": "# aiochannel - AsyncIO Channel\n\n[![Build Status](https://github.com/tbug/aiochannel/actions/workflows/test.yml/badge.svg)][Build Status]\n[![Stable Version](https://img.shields.io/pypi/v/aiochannel?label=stable)][PyPI Releases]\n[![Python Versions](https://img.shields.io/pypi/pyversions/aiochannel)][PyPI]\n[![Download Stats](https://img.shields.io/pypi/dm/aiochannel)](https://pypistats.org/packages/aiochannel)\n\nChannel concept for asyncio.\n\n\n## Install\n\n```\npip install aiochannel\n```\n\n## Changelog\n\n[Changelog]\n\n## Usage\n\n### Basics\n\n`Channel` has a very similar API to `asyncio.Queue`.\nThe key difference is that a channel is only considered\n\"done\" when it has been both closed and drained, so calling `.join()`\non a channel will wait for it to be both closed and drained (Unlike\n`Queue` which will return from `.join()` once the queue is empty).\n\n**NOTE:** Closing a channel is permanent. You cannot open it again.\n\n```python\nimport asyncio\nfrom aiochannel import Channel\n\n# ...\n\nasync def main():\n # A Channel takes a max queue size and an loop\n # both optional. loop is not recommended as\n # in asyncio is phasing out explicitly passed event-loop\n my_channel: Channel[str] = Channel(100)\n\n # You add items to the channel with\n await my_channel.put(\"my item\")\n # Note that this can throw ChannelClosed if the channel\n # is closed, during the attempt at adding the item\n # to the channel. Also note that .put() will block until\n # it can successfully add the item.\n\n\n # Retrieving is done with\n my_item = await my_channel.get()\n # Note that this can also throw ChannelClosed if the\n # channel is closed before or during retrival.\n # .get() will block until an item can be retrieved.\n\n # Note that this requires someone else to close and drain\n # the channel.\n # Lastly, you can close a channel with `my_channel.close()`\n # In this example, the event-loop call this asynchronously\n asyncio.get_event_loop().call_later(0.1, my_channel.close)\n\n # You can wait for the channel to be closed and drained:\n await my_channel.join()\n\n # Every call to .put() after .close() will fail with\n # a ChannelClosed.\n # you can check if a channel is marked for closing with\n if my_channel.closed():\n print (\"Channel is closed\")\n\nasyncio.run(main())\n```\n\nLike the `asyncio.Queue` you can also call non-async get and put:\n\n<!--pytest.mark.skip-->\n\n```python\n # non-async version of put\n my_channel.put_nowait(item)\n # This either returns None,\n # or raises ChannelClosed or ChannelFull\n\n # non-async version of get\n my_channel.get_nowait()\n # This either returns the next item from the channel\n # or raises ChannelEmpty or ChannelClosed\n # (Note that ChannelClosed emplies that the channel\n # is empty, but also that is will never fill again)\n```\n\nAs of `0.2.0` `Channel` also implements the async iterator protocol.\nYou can now use `async for` to iterate over the channel until it\ncloses, without having to deal with `ChannelClosed` exceptions.\n\n<!--pytest.mark.skip-->\n\n```python\n # the channel might contain data here\n async for item in channel:\n print(item)\n # the channel is closed and empty here\n```\n\nwhich is functionally equivalent to\n\n<!--pytest.mark.skip-->\n\n```python\n while True:\n try:\n data = yield from channel.get()\n except ChannelClosed:\n break\n # process data here\n```\n\n [PyPI]: https://pypi.org/project/aiochannel\n [PyPI Releases]: https://pypi.org/project/aiochannel/#history\n [Github]: https://github.com/tbug/aiochannel\n [Changelog]: https://github.com/tbug/aiochannel/blob/master/CHANGELOG.md\n [Issue Tracker]: https://github.com/tbug/aiochannel/issues\n [Build Status]: https://github.com/tbug/aiochannel/actions/workflows/test.yml\n",
"bugtrack_url": null,
"license": "Apache-2.0",
"summary": "asyncio Channels (closable queues) inspired by golang",
"version": "1.3.0",
"project_urls": {
"Homepage": "https://github.com/tbug/aiochannel",
"Source": "https://github.com/tbug/aiochannel",
"Tracker": "https://github.com/tbug/aiochannel/issues"
},
"split_keywords": [
"asyncio",
" aio",
" chan",
" channel",
" gochan"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "b3d12a03c8cbd475688929d6ebc5a98a8490c818b962a102554320fcb047baae",
"md5": "3af573c44a3a490b7d7a2e3125bc1112",
"sha256": "8f862b0ff92a8296cc76876301c9f82348ee12fe5a8bcc198399b921f1eef944"
},
"downloads": -1,
"filename": "aiochannel-1.3.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "3af573c44a3a490b7d7a2e3125bc1112",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.9",
"size": 5507,
"upload_time": "2024-12-09T08:55:52",
"upload_time_iso_8601": "2024-12-09T08:55:52.299863Z",
"url": "https://files.pythonhosted.org/packages/b3/d1/2a03c8cbd475688929d6ebc5a98a8490c818b962a102554320fcb047baae/aiochannel-1.3.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "3fa294d9fe4436bab8238120ff07b78043e9e4029fb1a102791c7a0b4475b6cb",
"md5": "f95a49c1a08af666220ba9bb59a60eb3",
"sha256": "212020426a9bddd29ad5039f16b9f86d8872bd8c22662aaf572189067d961b4f"
},
"downloads": -1,
"filename": "aiochannel-1.3.0.tar.gz",
"has_sig": false,
"md5_digest": "f95a49c1a08af666220ba9bb59a60eb3",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.9",
"size": 5323,
"upload_time": "2024-12-09T08:55:53",
"upload_time_iso_8601": "2024-12-09T08:55:53.912267Z",
"url": "https://files.pythonhosted.org/packages/3f/a2/94d9fe4436bab8238120ff07b78043e9e4029fb1a102791c7a0b4475b6cb/aiochannel-1.3.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-09 08:55:53",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "tbug",
"github_project": "aiochannel",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"tox": true,
"lcname": "aiochannel"
}