Skip to content

Add asyncio memory object channels (open_channel)#145356

Closed
kovan wants to merge 1 commit intopython:mainfrom
kovan:asyncio-memory-channels
Closed

Add asyncio memory object channels (open_channel)#145356
kovan wants to merge 1 commit intopython:mainfrom
kovan:asyncio-memory-channels

Conversation

@kovan
Copy link
Contributor

@kovan kovan commented Feb 28, 2026

Summary

Adds asyncio.open_channel(max_buffer_size) — a split send/receive channel primitive that improves on asyncio.Queue with:

  • Bounded by default — backpressure via max_buffer_size (supports 0 for rendezvous, math.inf for unbounded)
  • Split ownership — separate SendChannel / ReceiveChannel endpoints enforce correct resource management
  • Clone + ref-countingclone() enables multi-producer / multi-consumer (fan-in / fan-out) with clean shutdown
  • Async iterationasync for item in receive_channel
  • Deterministic close signalingEndOfChannel when all senders close, BrokenResourceError when all receivers close
  • Context manager support — both sync (with) and async (async with)

Part of the proposal to adopt proven anyio/Trio patterns natively into asyncio (Tier 2, item 2.2).

API

send, recv = asyncio.open_channel(max_buffer_size=10)

# Producer
await send.send(item)
send.close()

# Consumer
async for item in recv:
    process(item)
# StopAsyncIteration raised automatically when all senders close

New public names

  • asyncio.open_channel() — factory returning (SendChannel, ReceiveChannel)
  • asyncio.SendChannel — send endpoint with send(), send_nowait(), clone(), close()
  • asyncio.ReceiveChannel — receive endpoint with receive(), receive_nowait(), clone(), async iteration
  • asyncio.ChannelStatistics — frozen dataclass for introspection
  • asyncio.EndOfChannel — raised when all senders are closed
  • asyncio.ClosedResourceError — raised when using a closed endpoint
  • asyncio.BrokenResourceError — raised when sending with no open receivers
  • asyncio.WouldBlock — raised by _nowait methods when operation would block

Files

File Change
Lib/asyncio/channels.py New — channel implementation
Lib/asyncio/exceptions.py Add EndOfChannel, ClosedResourceError, BrokenResourceError, WouldBlock
Lib/asyncio/__init__.py Wire up channels module
Lib/test/test_asyncio/test_channels.py New — 40 tests

Test plan

  • ./python -m test test_asyncio.test_channels -v — all 40 tests pass
  • Verify no regressions in existing asyncio tests
  • Review for edge cases in cancellation and close ordering

🤖 Generated with Claude Code

Introduces open_channel() returning (SendChannel, ReceiveChannel) — a
bounded, split-ownership channel primitive for asyncio. Features include
ref-counted clone() for fan-in/fan-out patterns, backpressure via
max_buffer_size, deterministic close signaling (EndOfChannel when all
senders close, BrokenResourceError when all receivers close), and async
iteration support.

New exceptions: EndOfChannel, ClosedResourceError, BrokenResourceError,
WouldBlock.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ZeroIntensity
Copy link
Member

As with your other PR, please don't open PRs containing new features without first:

  1. Discussing the issue on DPO and getting a community consensus.
  2. Getting approval/endorsement from one of the asyncio maintainers.
  3. Opening an issue on GitHub.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants