From feb9a9fbde3282ad17fd546df851eb9b39f6af40 Mon Sep 17 00:00:00 2001 From: David Manthey Date: Mon, 1 Apr 2024 08:54:57 -0400 Subject: [PATCH] Reduce bioformats keeping file handles open When bioformats tries to open a zip file, it opens the file once per internal file. If it fails to find a file that can be opened within the zip, it throws an error and leaves all of the file handles open. By dividing the reader into more steps, we can ask to open an empty file, which somehow releases the file handles. --- CHANGELOG.md | 1 + .../large_image_source_bioformats/__init__.py | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed18b4e27..df9f04fcc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Add a dependency to the zarr source to read more compression types ([#1480](../../pull/1480)) - Guard fetching internal metadata on zarr sources that have less data ([#1481](../../pull/1481)) - Add a method to list registered extensions and mimetypes ([#1488](../../pull/1488)) +- Reduce bioformats keeping file handles open ([#1492](../../pull/1492)) ### Changes - Prohibit bioformats from reading zip directly ([#1491](../../pull/1491)) diff --git a/sources/bioformats/large_image_source_bioformats/__init__.py b/sources/bioformats/large_image_source_bioformats/__init__.py index 71477572f..c04b6ac0f 100644 --- a/sources/bioformats/large_image_source_bioformats/__init__.py +++ b/sources/bioformats/large_image_source_bioformats/__init__.py @@ -221,7 +221,21 @@ def __init__(self, path, **kwargs): # noqa try: javabridge.attach() try: - self._bioimage = bioformats.ImageReader(largeImagePath) + self._bioimage = bioformats.ImageReader(largeImagePath, perform_init=False) + try: + # So this as a separate step so, if it fails, we can ask to + # open something that does not exist and bioformats will + # release some file handles. + self._bioimage.init_reader() + except Exception as exc: + try: + # Ask to open a file that should never exist + self._bioimage.rdr.setId('__\0__') + except Exception: + pass + self._bioimage.close() + self._bioimage = None + raise exc except (AttributeError, OSError) as exc: if not os.path.isfile(largeImagePath): raise TileSourceFileNotFoundError(largeImagePath) from None