code: def load_module(self, fullname):
      if fullname in sys.modules:
          return sys.modules[fullname]
      if self._client is None:
          if sys.version_info[0] < 3:
              raise NotImplementedError(
                  "Environment escape imports are not supported in Python 2"
              )
          # We initialize a client and query the modules we handle
          # The max_pickle_version is the pickle version that the server (so
          # the underlying interpreter we call into) supports; we determine
          # what version the current environment support and take the minimum
          # of those two
          max_pickle_version = min(
              self._max_pickle_version, pickle.HIGHEST_PROTOCOL
          )
  
          self._client = Client(
              self._module_prefixes,
              self._python_executable,
              self._pythonpath,
              max_pickle_version,
              self._config_dir,
          )
          atexit.register(_clean_client, self._client)
  
          # Get information about overrides and what the server knows about
          exports = self._client.get_exports()
          ex_overrides = self._client.get_local_exception_overrides()
  
          prefixes = set()
          export_classes = exports.get("classes", [])
          export_functions = exports.get("functions", [])
          export_values = exports.get("values", [])
          export_exceptions = exports.get("exceptions", [])
          self._aliases = exports.get("aliases", {})
          for name in itertools.chain(
              export_classes, export_functions, export_values
          ):
              splits = name.rsplit(".", 1)
              prefixes.add(splits[0])
  
          # Now look at the exceptions coming from the server
          formed_exception_classes = {}
          for ex_name, ex_parents in export_exceptions:
              # Exception is a tuple (name, (parents,))
              # Exceptions are also given in order of instantiation (ie: the
              # server already topologically sorted them)
              ex_class_dict = ex_overrides.get(ex_name, None)
              if ex_class_dict is None:
                  ex_class_dict = {}
              else:
                  ex_class_dict = dict(ex_class_dict.__dict__)
              parents = []
              for fake_base in ex_parents:
                  if fake_base.startswith("builtins."):
                      # This is something we know of here
                      parents.append(eval(fake_base[9:]))
                  else:
                      # It's in formed_classes
                      parents.append(
                          formed_exception_classes[fake_base]
                      )
              splits = ex_name.rsplit(".", 1)
              ex_class_dict["__user_defined__"] = set(
                  ex_class_dict.keys()
              )
              new_class = type(splits[1], tuple(parents), ex_class_dict)
              new_class.__module__ = splits[0]
              new_class.__name__ = splits[1]
              formed_exception_classes[ex_name] = new_class
  
          # Now update prefixes as needed
          for name in formed_exception_classes:
              splits = name.rsplit(".", 1)
              prefixes.add(splits[0])
  
          # We will make sure that we create modules even for "empty" prefixes
          # because packages are always loaded hierarchically so if we have
          # something in `a.b.c` but nothing directly in `a`, we still need to
          # create a module named `a`. There is probably a better way of doing this
          all_prefixes = list(prefixes)
          for prefix in all_prefixes:
              parts = prefix.split(".")
              cur = parts[0]
              for i in range(1, len(parts)):
                  prefixes.add(cur)
                  cur = ".".join([cur, parts[i]])
  
          # We now know all the modules that we can handle. We update
          # handled_module and return the module if we have it or raise ImportError
          self._handled_modules = {}
          for prefix in prefixes:
              self._handled_modules[prefix] = _WrappedModule(
                  self,
                  prefix,
                  exports,
                  formed_exception_classes,
                  self._client,
              )
      canonical_fullname = get_canonical_name(fullname, self._aliases)
      # Modules are created canonically but we need to return something for any
      # of the aliases.
      module = self._handled_modules.get(canonical_fullname)
      if module is None:
          raise ImportError
      sys.modules[fullname] = module
      return module
  
imports: import atexit
  import importlib
  import itertools
  import pickle
  import re
  import sys
  from .consts import OP_CALLFUNC, OP_GETVAL, OP_SETVAL
  from .client import Client
  from .override_decorators import LocalException
  from .utils import get_canonical_name
label_desc: Use image node_id 3 for calling the ModuleImporter obj's underlying member method code with example usage: obj.load_module(fullname) and returns: module, sys