Skip to content

Selecting¤

Select the first among multiple Receivers.

Usage¤

If you need to receiver different types of messages from different receivers, you need to know the source of a particular received message to know the type of the message.

select() allows you to do that. It is an async iterator that will iterate over the messages of all receivers as they receive new messages.

It yields a Selected object that will tell you the source of the received message. To make sure the received message is cast to the correct type, you need to use the selected_from() function to check the source of the message, and the message attribute to access the message:

async for selected in select(receiver1, receiver2):
    if selected_from(selected, receiver1):
        print(f"Received from receiver1, next number: {selected.message + 1}")
    elif selected_from(selected, receiver2):
        print(f"Received from receiver2, length: {len(selected.message)}")
    else:
        assert False, "Unknown source, this should never happen"
Tip

To prevent common bugs, like when a new receiver is added to the select loop but the handling code is forgotten, select() will check that all the selected receivers are handled in the if-chain.

If this happens, it will raise an UnhandledSelectedError exception.

If for some reason you want to ignore a received message, just add the receiver to the if-chain and do nothing with the message:

async for selected in select(receiver1, receiver2):
    if selected_from(selected, receiver1):
        continue
    if selected_from(selected, receiver2):
        print(f"Received from receiver2, length: {len(selected.message)}")

Stopping¤

The select() async iterator will stop as soon as all the receivers are stopped. You can also end the iteration early by breaking out of the loop as normal.

When a single receiver is stopped, it will be reported via the Selected object. You can use the was_stopped method to check if the selected receiver was stopped:

async for selected in select(receiver1, receiver2):
    if selected_from(selected, receiver1):
        if selected.was_stopped:
            print("receiver1 was stopped")
            continue
        print(f"Received from receiver1, the next number is: {selected.message + 1}")
    # ...
Tip

The was_stopped method is a convenience method that is equivalent to checking if the exception attribute is an instance of ReceiverStoppedError.

Error Handling¤

Tip

For more information about handling errors, please refer to the Error Handling section of the user guide.

If a receiver raises an exception while receiving a message, the exception will be raised by the message attribute of the Selected object.

You can use a try-except block to handle exceptions as usual:

async for selected in select(receiver1, receiver2):
    if selected_from(selected, receiver1):
        try:
            print(f"Received from receiver1, next number: {selected.message + 1}")
        except ReceiverStoppedError:
            print("receiver1 was stopped")
        except ValueError as value_error:
            print(f"receiver1 raised a ValueError: {value_error}")
        # ...
    # ...

The Selected object also has a exception attribute that will contain the exception that was raised by the receiver.