Streams¶
| Name | What it does |
|---|---|
SharedStream |
a named ring of typed items in shared memory, sent by one process and received by up to max_readers readers |
SharedSendStream |
the one sender of a stream, with blocking, non-blocking and asyncio sends |
SendSlot |
a slot reserved by writing: its item, whose arrays are filled in place, and send |
SharedReceiveStream |
a reader of a stream, in mode lossless, lossy or latest |
ReceiveEvents |
the psygnal signal group of a reader: received for each item and ended once |
SharedStreamStatistics |
a stream's state at one moment: what was sent, what the ring holds and who reads it |
ReceiveStreamStatistics |
one open reader of a stream: its mode, position, lag and process |
SharedStream
¶
Bases: Generic[T]
A ring of items in shared memory, sent by one process and received by up to max_readers readers.
Create it with create in one process,
and open it with attach in others or
pass it to them, as a process argument for instance: a pickled stream
attaches again, and refuses a stream created since under the same name
with SchemaMismatchError. Every item has the type given there: any type a
SharedBox field takes, except a reference to a box.
create
classmethod
¶
create(item_type: object, name: str | None = None, *, capacity: int, max_readers: int = 8) -> SharedStream[Any]
Create the stream name holding capacity items of item_type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str | None
|
Without one, the stream gets a new name of 16 hex digits. A
process the stream is passed to opens it without being told the
name, so only code that calls |
None
|
capacity
|
int
|
Items the ring holds, at least 2. A lossless reader may fall
this many items behind before |
required |
max_readers
|
int
|
Readers that may be open at once, 1 to 4095. |
8
|
Raises:
| Type | Description |
|---|---|
SegmentExistsError
|
If the name is taken. |
TypeError
|
If a box field could not hold |
ValueError
|
If the name breaks the naming rules, or |
attach
classmethod
¶
Open the stream name, whose items must have the type item_type.
Raises:
| Type | Description |
|---|---|
SegmentNotFoundError
|
If no stream has that name, or it does not become one within 1 s. |
KindMismatchError
|
If the name holds a segment of another kind, such as a box. |
SchemaMismatchError
|
If the stream holds items of another type. |
unlink
staticmethod
¶
Remove the name name on Linux, as SharedBox.unlink does; a no-op on Windows.
sender
¶
Return the stream's sender for this process.
Raises:
| Type | Description |
|---|---|
StreamBusyError
|
If another live end holds the sender. |
EndOfStream
|
If the stream has ended: its sender closed, or a reader found the sender's process dead. There is no second sender after that. |
Notes
A sender whose process died is replaced, unless a reader already found it dead, which ended the stream.
The stream keeps its sender until it is closed, so dropping the
returned object does not end the stream, and another sender() call
in this process raises StreamBusyError until then.
reader
¶
Open a reader.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mode
|
Mode
|
|
'lossless'
|
start
|
Start
|
|
'newest'
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
WaiterSlotsFullError
|
If |
statistics
¶
Return what was sent, what the ring holds, and each open reader's state.
close
¶
Close every sender and reader made from this object, then let go of the stream.
Closing the sender ends the stream for its readers.
Other processes keep the stream. Using a closed stream raises
StreamClosedError.
SharedSendStream
¶
Bases: End, Generic[T]
The sender of a stream: one per stream, in the process that holds it.
SharedStream.sender returns it. The
stream keeps it open until close(), or until the stream is closed or
the process dies; dropping the object does not close it.
Closing it ends the stream: readers receive what is buffered, then
EndOfStream.
send
¶
Send item, waiting while a lossless reader is a full ring behind.
The item is encoded straight into its slot once the slot is free, so an item that cannot be encoded raises only after that wait.
Raises:
| Type | Description |
|---|---|
TimeoutError
|
If |
StreamClosedError
|
If this sender is closed, before or during the wait. |
RuntimeError
|
If called inside a block of this sender's
|
Notes
An interrupt such as Ctrl-C during the call may leave the item sent although the call raised.
asend
async
¶
Send item, as send does, without blocking the event loop.
A cancelled asend may still have sent its item, if a reader made
room just as it was cancelled.
Raises:
| Type | Description |
|---|---|
StreamClosedError
|
If this sender is closed, before or during the wait. |
RuntimeError
|
If called inside a block of this sender's |
send_nowait
¶
Send item, or raise WouldBlock if that needs a wait.
It would wait while a lossless reader is a full ring behind, or while
another thread or task holds the slot from
writing or
awriting.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If called inside a block of this sender's |
writing
¶
writing(template: T | None = None, timeout: float | None = None) -> Generator[SendSlot[T], None, None]
Reserve the next slot and yield it, to fill the item's arrays in place and send it.
slot.item is an item built from
template, with each array it reaches through records and tuples
replaced by a writable array over the slot. The template's own
arrays are never read, so they may be empty. The block fills the
slot's arrays and sends the item with
slot.send, which does not copy them:
blank = Letter(0, "", np.empty((0, 0), np.uint8))
with sender.writing(blank) as slot:
scanner.read_into(slot.item.scan)
slot.send(replace(slot.item, index=n))
An item that is an array needs no template. Leaving the block
without send, or by an exception, gives the slot up: nothing is
published, and the next send takes its position. Until the slot is
sent or the block ends, readers see nothing new, and a send or
writing on this sender from another thread or task waits. That
includes a task started inside the block by asyncio.wait_for or
create_task.
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If a value of |
TimeoutError
|
If |
StreamClosedError
|
If this sender is closed, before or during the wait. |
RuntimeError
|
If called inside a block of this sender's |
Notes
An interrupt such as Ctrl-C just before the block starts may leave the slot reserved with no block to give it up, so later sends on this sender wait until they time out. Closing the sender ends them.
awriting
async
¶
Reserve the next slot, as writing does, without blocking the event loop.
A cancelled awriting reserves nothing.
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
StreamClosedError
|
If this sender is closed, before or during the wait. |
RuntimeError
|
If called inside a block of this sender's |
SendSlot
¶
Bases: Slot[T]
A slot of a stream that SharedSendStream.writing reserved for one item.
writing and
awriting make it. Its
item holds arrays over the slot, which
the block fills, and send publishes an
item.
item
property
¶
The item to fill: the template's members, with arrays over the slot.
Each array the item reaches through records and tuples is a writable
array of its member's declared type, dtype and shape, which views
the slot in shared memory and starts with the bytes of an older
item. The arrays keep the stream's mapping alive, so using them
after the block or after the stream is closed cannot crash, but
writing to them after send changes
an item readers may have received and tells no one.
send
¶
Encode item into the slot and publish it.
An array of item that already is its place in the slot, such as
one of item's arrays, is not copied;
any other array is copied into the slot.
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If this slot was sent or given up already. |
StreamClosedError
|
If the sender was closed after the slot was reserved; nothing is published. |
TypeError
|
If |
ValueError
|
If a value in |
SharedReceiveStream
¶
Bases: End, Iterator[T], AsyncIterator[T], Generic[T]
A reader of a stream, in the process that opened it.
SharedStream.reader returns it.
for item in reader and async for item in reader receive until the
stream ends.
Notes
Receives made with receive and the like must not overlap receives made
with receive_future or async for on the same reader: an item that an
awaiting task gave up is kept and returned by the next receive, which may
then come after a later item.
position
property
¶
The position of the last item received, None before the first.
ReceiveStreamStatistics.position
is the position of the item received next, so right after a receive
it is one more than this.
missed
property
¶
Items a lossy or latest reader skipped; always 0 for a lossless reader.
events
property
¶
The reader's psygnal signals: received as (item, position) for each item, and ended once per delivery.
Connecting the first received callback starts delivery on the reader's
background thread, and disconnecting the last one stops it. While
delivery runs, every other way of receiving from this reader raises
RuntimeError, also after the stream has ended, until the callbacks
disconnect: one reader cannot hand an item to two consumers, so
open a second reader for that. Callbacks run on the background
thread; connect with thread="main" and call
psygnal.emit_queued() to run them on the main thread. A callback
that raises is logged to the sharedbox logger and delivery goes
on, unless the receive itself fails: that is logged too, and callbacks
then receive nothing more until a received callback connects or disconnects.
Delivery runs only while received has a callback, and ended fires
only then. A slow callback makes a lossy or latest
reader miss items and holds the sender back for a lossless one.
Right after delivery stops, the _nowait forms may raise WouldBlock
until the delivering call has returned.
Notes
Starting and stopping delivery relies on psygnal calling the private
methods SignalInstance._append_slot and _remove_slot.
receive
¶
Return the next item, with new arrays.
Raises:
| Type | Description |
|---|---|
EndOfStream
|
If the sender closed or died and every item it sent was received. |
TimeoutError
|
If |
StreamClosedError
|
If this reader is closed, before or during the wait. |
Notes
A blocking receive first waits for calls already on the reader's
background thread, such as an outstanding
receive_future, and
returns the item after theirs; that wait counts against timeout.
An interrupt such as Ctrl-C during the call may lose the item being
received.
receive_into
¶
Return the next item, with its arrays read into the arrays in out.
out has the item's shape: an array for an item that is an array, a
tuple with an entry per member for a tuple item, and a mapping from
member name to entry for a record item. An entry is an array, None
for a member decoded as usual, or, for a member that is a record or a
tuple, an out of its own shape. A name left out of a mapping is
decoded as usual. The item returned holds your arrays, filled in
place. Allocate the arrays once and pass them to every call:
scan = np.empty((32, 32), np.uint8)
letter = reader.receive_into({"scan": scan})
An item that a cancelled receive_future or anext had already
received is returned by the next receive of any kind, and holds the
arrays of the call that received it, not out.
A member that is a list, set, frozenset, dict or tuple[T, ...]
takes None, since an array cannot be a collection element, and an
item that is a collection has no array to read into. Every check
runs before anything is received, so a refused call takes no item.
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If an array has another dtype or shape than its member. |
Notes
A blocking receive first waits for calls already on the reader's
background thread, such as an outstanding
receive_future, and
returns the item after theirs; that wait counts against timeout.
After an exception the contents of out are unspecified. out must
not be written to or resized from another thread during the call. An
interrupt such as Ctrl-C during the call may lose the item being
received.
receive_nowait
¶
Return the next item, or raise WouldBlock if none is waiting.
It also raises WouldBlock while a call on the reader's background
thread is still running, such as a cancelled anext or a delivery
stopping after the last events.received callback disconnected, so
an item that call hands back is received first.
receive_into_nowait
¶
As receive_into, raising WouldBlock if no item is waiting.
iter_into
¶
Return an iterator of items read into the arrays in out, as receive_into takes it, for for.
receive_future
¶
Return a future of the next item, received by this reader's background thread.
The future is a concurrent.futures.Future, so
concurrent.futures.wait and asyncio.wrap_future take it. Its
exception is EndOfStream once the stream
has ended, and StreamClosedError if
the reader closes first. out, when given, is what
receive_into takes.
Cancel the future before it starts to drop it. A running call cannot
be cancelled: cancel() returns False, as for any Future, and the
call goes on. An item it takes after its future was abandoned, or
after an asyncio.wrap_future around it was cancelled, is lost. To
wait on several readers, keep one outstanding future per reader and
submit a new one only for the readers whose future completed.
ReceiveEvents
¶
Bases: SignalGroup
The psygnal signal group of a stream reader.
It is the type of SharedReceiveStream.events.
Create the signal group of a stream reader.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
reader
|
SharedReceiveStream[Any] | None
|
The reader whose delivery starts and stops with the |
None
|
SharedStreamStatistics
dataclass
¶
ReceiveStreamStatistics
dataclass
¶
One open reader of a stream, as SharedStream.statistics found it.
position
instance-attribute
¶
The position of the item the reader receives next, at most sent.
Right after a receive it is one more than
SharedReceiveStream.position,
the position of the item received, except for the moment before the
sender counts that item in sent.