diff --git a/otbtf/__init__.py b/otbtf/__init__.py
index 5321e3dba52898934094bdfa5df8efd6cc0d83d7..6ee17f9ebed316dba9c575238dab96716b2d3a24 100644
--- a/otbtf/__init__.py
+++ b/otbtf/__init__.py
@@ -20,9 +20,12 @@
 """
 OTBTF python module
 """
+try:
+    from otbtf.utils import read_as_np_arr, gdal_open
+    from otbtf.dataset import Buffer, PatchesReaderBase, PatchesImagesReader, IteratorBase, RandomIterator, Dataset, \
+        DatasetFromPatchesImages
+except ImportError:
+    print("Warning: otbtf.utils and otbtf.dataset were not imported. Using OTBTF without GDAL.")
 
-from otbtf.utils import read_as_np_arr, gdal_open
-from otbtf.dataset import Buffer, PatchesReaderBase, PatchesImagesReader, IteratorBase, RandomIterator, Dataset, \
-     DatasetFromPatchesImages
 from otbtf.tfrecords import TFRecords
 from otbtf.model import ModelBase
diff --git a/otbtf/model.py b/otbtf/model.py
index a6306e273200e94fd83c335fe2f165f17dbfb4ab..38fc6ca6044d74cd583b5d616b2d7a377f2e1f37 100644
--- a/otbtf/model.py
+++ b/otbtf/model.py
@@ -3,7 +3,6 @@
 import abc
 import logging
 import tensorflow
-from otbtf.utils import _is_chief, cropped_tensor_name
 
 
 class ModelBase(abc.ABC):
@@ -165,3 +164,37 @@ class ModelBase(abc.ABC):
             model_simplified = tensorflow.keras.Model(inputs=inputs, outputs=outputs,
                                                       name=self.__class__.__name__ + '_simplified')
             tensorflow.keras.utils.plot_model(model_simplified, output_path)
+
+
+def _is_chief(strategy):
+    """
+    Tell if the current worker is the chief.
+
+    :param strategy: strategy
+    :return: True if the current worker is the chief, False else
+    """
+    # Note: there are two possible `TF_CONFIG` configuration.
+    #   1) In addition to `worker` tasks, a `chief` task type is use;
+    #      in this case, this function should be modified to
+    #      `return task_type == 'chief'`.
+    #   2) Only `worker` task type is used; in this case, worker 0 is
+    #      regarded as the chief. The implementation demonstrated here
+    #      is for this case.
+    # For the purpose of this Colab section, the `task_type is None` case
+    # is added because it is effectively run with only a single worker.
+
+    if strategy.cluster_resolver:  # this means MultiWorkerMirroredStrategy
+        task_type, task_id = strategy.cluster_resolver.task_type, strategy.cluster_resolver.task_id
+        return (task_type == 'chief') or (task_type == 'worker' and task_id == 0) or task_type is None
+    # strategy with only one worker
+    return True
+
+
+def cropped_tensor_name(tensor_name, crop):
+    """
+    A name for the padded tensor
+    :param tensor_name: tensor name
+    :param pad: pad value
+    :return: name
+    """
+    return "{}_crop{}".format(tensor_name, crop)
diff --git a/otbtf/utils.py b/otbtf/utils.py
index 7aa777af75e3b92bdacde6d28c3b1b1e6072de4b..069638a551e0226c9ff3ad6cc1537359922b29c1 100644
--- a/otbtf/utils.py
+++ b/otbtf/utils.py
@@ -63,37 +63,3 @@ def read_as_np_arr(gdal_ds, as_patches=True, dtype=None):
         buffer = buffer.astype(dtype)
 
     return buffer
-
-
-def _is_chief(strategy):
-    """
-    Tell if the current worker is the chief.
-
-    :param strategy: strategy
-    :return: True if the current worker is the chief, False else
-    """
-    # Note: there are two possible `TF_CONFIG` configuration.
-    #   1) In addition to `worker` tasks, a `chief` task type is use;
-    #      in this case, this function should be modified to
-    #      `return task_type == 'chief'`.
-    #   2) Only `worker` task type is used; in this case, worker 0 is
-    #      regarded as the chief. The implementation demonstrated here
-    #      is for this case.
-    # For the purpose of this Colab section, the `task_type is None` case
-    # is added because it is effectively run with only a single worker.
-
-    if strategy.cluster_resolver:  # this means MultiWorkerMirroredStrategy
-        task_type, task_id = strategy.cluster_resolver.task_type, strategy.cluster_resolver.task_id
-        return (task_type == 'chief') or (task_type == 'worker' and task_id == 0) or task_type is None
-    # strategy with only one worker
-    return True
-
-
-def cropped_tensor_name(tensor_name, crop):
-    """
-    A name for the padded tensor
-    :param tensor_name: tensor name
-    :param pad: pad value
-    :return: name
-    """
-    return "{}_crop{}".format(tensor_name, crop)