Skip to content

Commit 89f84fa

Browse files
committed
Improve the _exceptions module description
Explain the base exceptions and the basics of error handling, including how to get the cause of an exception. This module is not publicly available, so users won't be able to access the information in IDEs for example, but it will be rendered as part of the User Guide. Signed-off-by: Leandro Lucarella <[email protected]>
1 parent 5b340e5 commit 89f84fa

File tree

1 file changed

+64
-1
lines changed

1 file changed

+64
-1
lines changed

src/frequenz/channels/_exceptions.py

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,70 @@
11
# License: MIT
22
# Copyright © 2022 Frequenz Energy-as-a-Service GmbH
33

4-
"""Base exception classes."""
4+
"""Base exception classes.
5+
6+
# Exceptions
7+
8+
All exceptions generated by this library inherit from the
9+
[`Error`][frequenz.channels.Error] exception.
10+
11+
Exceptions generated by channels inherit from the
12+
[`ChannelError`][frequenz.channels.ChannelError] exception. When there is an attempt to
13+
use a closed channel, a [`ChannelClosedError`][frequenz.channels.ChannelClosedError]
14+
exception is raised.
15+
16+
# Causes
17+
18+
When a exception is caused by another exception, for example if the underlying channel
19+
was closed while seding or receiving a message, the original exception will be
20+
available as the cause of the exception:
21+
22+
```python
23+
from frequenz.channels import Anycast, ChannelClosedError, SenderError
24+
25+
channel = Anycast[int](name="test-channel")
26+
sender = channel.new_sender()
27+
28+
try:
29+
await sender.send(42)
30+
except SenderError as error:
31+
match error.__cause__:
32+
case None:
33+
print("The message couldn't be sent for an known reason")
34+
case ChannelClosedError() as closed_error:
35+
print(f"The message couldn't be sent, channel closed: {closed_error}")
36+
case _ as unknown_error:
37+
print(f"The message couldn't be sent: {unknown_error}")
38+
```
39+
40+
Tip:
41+
If you are using the async iteration interface for receivers, then you can
42+
access the cause of the
43+
[`ReceiverStoppedError`][frequenz.channels.ReceiverStoppedError] exception by
44+
explicitly calling [`receive()`][frequenz.channels.Receiver.receive] on the
45+
receiver after the iteration is done:
46+
47+
```python
48+
from frequenz.channels import Anycast, ChannelClosedError, ReceiverStoppedError
49+
50+
channel = Anycast[int](name="test-channel")
51+
receiver = channel.new_receiver()
52+
53+
async for value in receiver:
54+
print(value)
55+
try:
56+
await receiver.receive()
57+
except ReceiverStoppedError as error:
58+
print("The receiver was stopped")
59+
match error.__cause__:
60+
case None:
61+
print("The receiver was stopped without a known reason")
62+
case ChannelClosedError() as closed_error:
63+
print(f"The channel was closed with error: {closed_error}")
64+
case _ as unknown_error:
65+
print(f"The receiver was stopped due to an unknown error: {unknown_error}")
66+
```
67+
"""
568

669
from typing import Any
770

0 commit comments

Comments
 (0)