Basic sends and receives on channels are blocking in Python's `asyncio` library. However, we can use `asyncio.wait()` with a timeout to implement non-blocking operations, similar to the `select` with a `default` clause in other languages.
```python
import asyncio
async def main():
messages = asyncio.Queue()
signals = asyncio.Queue()
# Here's a non-blocking receive. If a value is
# available on `messages` then it will be retrieved.
# If not, it will immediately move on.
try:
msg = await asyncio.wait_for(messages.get(), timeout=0.01)
print(f"received message {msg}")
except asyncio.TimeoutError:
print("no message received")
# A non-blocking send works similarly. Here `msg`
# is attempted to be sent to the `messages` queue,
# but if it can't be sent immediately, it moves on.
msg = "hi"
try:
await asyncio.wait_for(messages.put(msg), timeout=0.01)
print(f"sent message {msg}")
except asyncio.TimeoutError:
print("no message sent")
# We can use multiple try-except blocks to implement
# a multi-way non-blocking select. Here we attempt
# non-blocking receives on both `messages` and `signals` .
done, pending = await asyncio.wait([
messages.get(),
signals.get()
], timeout=0.01, return_when=asyncio.FIRST_COMPLETED)
if done:
for task in done:
result = task.result()
if task == messages.get():
print(f"received message {result}")
elif task == signals.get():
print(f"received signal {result}")
else:
print("no activity")
asyncio.run(main())