Skip to content

Commit 70a406d

Browse files
committed
improve: add helpful error message for missing tensorboard package
TensorBoardHandler raised an opaque OptionalImportError when tensorboard was not installed. Raise a RuntimeError with install instructions instead. optional_import() returns a lazy-raising stub on failure rather than None, so the availability flag it returns must be captured and checked -- a 'SummaryWriter is None' guard would never fire. _tb_available is also bound in the TYPE_CHECKING branch so static analysis can see it. Adds a regression test that patches the flag to simulate the package being absent. Signed-off-by: skdas20 <skdas5405@gmail.com>
1 parent 3ee058b commit 70a406d

2 files changed

Lines changed: 21 additions & 2 deletions

File tree

monai/handlers/tensorboard_handlers.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,13 @@
2727
from ignite.engine import Engine
2828
from tensorboardX import SummaryWriter as SummaryWriterX
2929
from torch.utils.tensorboard import SummaryWriter
30+
31+
_tb_available = True
3032
else:
3133
Engine, _ = optional_import(
3234
"ignite.engine", IgniteInfo.OPT_IMPORT_VERSION, min_version, "Engine", as_type="decorator"
3335
)
34-
SummaryWriter, _ = optional_import("torch.utils.tensorboard", name="SummaryWriter")
36+
SummaryWriter, _tb_available = optional_import("torch.utils.tensorboard", name="SummaryWriter")
3537
SummaryWriterX, _ = optional_import("tensorboardX", name="SummaryWriter")
3638

3739
DEFAULT_TAG = "Loss"
@@ -46,10 +48,18 @@ class TensorBoardHandler:
4648
default to create a new TensorBoard writer.
4749
log_dir: if using default SummaryWriter, write logs to this directory, default is `./runs`.
4850
51+
Raises:
52+
RuntimeError: When ``summary_writer`` is ``None`` and the ``tensorboard`` package is not installed.
53+
4954
"""
5055

5156
def __init__(self, summary_writer: SummaryWriter | SummaryWriterX | None = None, log_dir: str = "./runs"):
5257
if summary_writer is None:
58+
if not _tb_available:
59+
raise RuntimeError(
60+
"TensorBoardHandler requires tensorboard to be installed. "
61+
"Please install it with: pip install tensorboard"
62+
)
5363
self._writer = SummaryWriter(log_dir=log_dir)
5464
self.internal_writer = True
5565
else:

tests/handlers/test_handler_tb_stats.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@
1414
import glob
1515
import tempfile
1616
import unittest
17-
from unittest.mock import MagicMock
17+
from unittest.mock import MagicMock, patch
1818

1919
from ignite.engine import Engine, Events
2020
from parameterized import parameterized
2121

2222
from monai.handlers import TensorBoardStatsHandler
23+
from monai.handlers.tensorboard_handlers import TensorBoardHandler
2324
from monai.utils import optional_import
2425

2526
SummaryWriter, has_tb = optional_import("torch.utils.tensorboard", name="SummaryWriter")
@@ -162,5 +163,13 @@ def _update_metric(engine):
162163
) # 2 = len([1, 3]) from event_filter
163164

164165

166+
class TestTensorBoardHandlerMissingDependency(unittest.TestCase):
167+
168+
def test_raises_when_tensorboard_unavailable(self):
169+
with patch("monai.handlers.tensorboard_handlers._tb_available", False):
170+
with self.assertRaises(RuntimeError):
171+
TensorBoardHandler()
172+
173+
165174
if __name__ == "__main__":
166175
unittest.main()

0 commit comments

Comments
 (0)