Skip to content

Commit

Permalink
Have many sources use lazy imports
Browse files Browse the repository at this point in the history
  • Loading branch information
manthey committed Jul 16, 2024
1 parent 4b1841d commit c52f8e5
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 51 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

- Improve plottable data endpoint to better fetch adjacent items and annotations ([#1573](../../pull/1573), [#1574](../../pull/1574))), [#1575](../../pull/1575)))
- Support Girder flat-mount paths ([#1576](../../pull/1576))
- Lazily import some modules to speed up large_image import speed ([#1577](../../pull/1577))
- Create or check large images for each item in a folder ([#1572](../../pull/1572))

## 1.29.2

Expand Down
65 changes: 46 additions & 19 deletions sources/gdal/large_image_source_gdal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,11 @@
import struct
import tempfile
import threading
from importlib.metadata import PackageNotFoundError
from importlib.metadata import version as _importlib_version

import numpy as np
import PIL.Image
from osgeo import gdal, gdal_array, gdalconst, osr

try:
gdal.UseExceptions()
except Exception:
pass

# isort: off

# pyproj stopped supporting older pythons, so on those versions its database is
# aging; as such, if on those older versions of python if it is imported before
# gdal, there can be a database version conflict; importing after gdal avoids
# this.
import pyproj

# isort: on

from importlib.metadata import PackageNotFoundError
from importlib.metadata import version as _importlib_version

from large_image.cache_util import LruCacheMetaclass, methodcache
from large_image.constants import (TILE_FORMAT_IMAGE, TILE_FORMAT_NUMPY,
Expand All @@ -62,6 +45,42 @@
# package is not installed
pass

gdal = None
gdal_array = None
gdalconst = None
osr = None
pyproj = None


def _lazyImport():
"""
Import the gdal module. This is done when needed rather than in the
module initialization because it is slow.
"""
global gdal, gdal_array, gdalconst, osr, pyproj

if gdal is None:
try:
from osgeo import gdal, gdal_array, gdalconst, osr

try:
gdal.UseExceptions()
except Exception:
pass

# isort: off

# pyproj stopped supporting older pythons, so on those versions its
# database is aging; as such, if on those older versions of python
# if it is imported before gdal, there can be a database version
# conflict; importing after gdal avoids this.
import pyproj

# isort: on
except ImportError:
msg = 'gdal module not found.'
raise TileSourceError(msg)


class GDALFileTileSource(GDALBaseFileTileSource, metaclass=LruCacheMetaclass):
"""
Expand Down Expand Up @@ -91,6 +110,8 @@ def __init__(self, path, projection=None, unitsPerPixel=None, **kwargs):
specify unitsPerPixel.
"""
super().__init__(path, **kwargs)
_lazyImport()

self.addKnownExtensions()
self._bounds = {}
self._largeImagePath = self._getLargeImagePath()
Expand Down Expand Up @@ -300,6 +321,8 @@ def _proj4Proj(proj):
:returns: a proj4 projection object. None if the specified projection
cannot be created.
"""
_lazyImport()

if isinstance(proj, bytes):
proj = proj.decode()
if not isinstance(proj, str):
Expand Down Expand Up @@ -940,6 +963,8 @@ def isGeospatial(path):
:param path: The path to the file
:returns: True if geospatial.
"""
_lazyImport()

try:
ds = gdal.Open(str(path), gdalconst.GA_ReadOnly)
except Exception:
Expand All @@ -958,6 +983,8 @@ def isGeospatial(path):
@classmethod
def addKnownExtensions(cls):
if not hasattr(cls, '_addedExtensions'):
_lazyImport()

cls._addedExtensions = True
cls.extensions = cls.extensions.copy()
cls.mimeTypes = cls.mimeTypes.copy()
Expand Down
25 changes: 22 additions & 3 deletions sources/multi/large_image_source_multi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from importlib.metadata import version as _importlib_version
from pathlib import Path

import jsonschema
import numpy as np
import yaml

Expand All @@ -27,6 +26,26 @@
# package is not installed
pass

jsonschema = None
_validator = None


def _lazyImport():
"""
Import the jsonschema module. This is done when needed rather than in the
module initialization because it is slow.
"""
global jsonschema, _validator

if jsonschema is None:
try:
import jsonschema

_validator = jsonschema.Draft6Validator(MultiSourceSchema)
except ImportError:
msg = 'jsonschema module not found.'
raise TileSourceError(msg)


SourceEntrySchema = {
'type': 'object',
Expand Down Expand Up @@ -387,8 +406,6 @@ class MultiFileTileSource(FileTileSource, metaclass=LruCacheMetaclass):
_defaultTileSize = 256
_maxOpenHandles = 6

_validator = jsonschema.Draft6Validator(MultiSourceSchema)

def __init__(self, path, **kwargs):
"""
Initialize the tile class. See the base class for other available
Expand All @@ -398,6 +415,8 @@ def __init__(self, path, **kwargs):
"""
super().__init__(path, **kwargs)

_lazyImport()
self._validator = _validator
self._largeImagePath = self._getLargeImagePath()
self._lastOpenSourceLock = threading.RLock()
# 'c' must be first as channels are special because they can have names
Expand Down
19 changes: 18 additions & 1 deletion sources/openjpeg/large_image_source_openjpeg/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
from importlib.metadata import version as _importlib_version
from xml.etree import ElementTree

import glymur
import PIL.Image

import large_image
Expand All @@ -41,6 +40,23 @@
# package is not installed
pass

glymur = None


def _lazyImport():
"""
Import the glymur module. This is done when needed rather than in the module
initialization because it is slow.
"""
global glymur

if glymur is None:
try:
import glymur
except ImportError:
msg = 'glymur module not found.'
raise TileSourceError(msg)


warnings.filterwarnings('ignore', category=UserWarning, module='glymur')

Expand Down Expand Up @@ -88,6 +104,7 @@ def __init__(self, path, **kwargs):
"""
super().__init__(path, **kwargs)

_lazyImport()
self._largeImagePath = str(self._getLargeImagePath())
self._pixelInfo = {}
try:
Expand Down
Loading

0 comments on commit c52f8e5

Please sign in to comment.