Skip to content

Commit f58f7c9

Browse files
committed
fix: disable tqdm in CI environments to prevent threading deadlock
This commit addresses the threading deadlock issue that occurs in headless CI/CD environments (particularly on Linux) when tqdm's monitor thread interacts with CZI file reading operations. Changes: - Added _should_use_tqdm() helper function to detect CI/headless environments - Modified planetable.py to conditionally use tqdm based on environment - Modified read_tools.py to conditionally use tqdm based on environment - tqdm is disabled when CI=true, GITHUB_ACTIONS=true, TQDM_DISABLE=1, or QT_QPA_PLATFORM=offscreen - Falls back to itertools.product and no-op tqdm wrapper when disabled - Maintains full compatibility - progress bars work normally in interactive environments Fixes: Threading deadlock on Linux CI when reading CZI files
1 parent c1053ca commit f58f7c9

File tree

2 files changed

+71
-3
lines changed

2 files changed

+71
-3
lines changed

src/czitools/read_tools/read_tools.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,45 @@
1313
import gc
1414
import warnings
1515
import itertools
16+
import os
17+
18+
19+
def _should_use_tqdm() -> bool:
20+
"""
21+
Determine if tqdm progress bars should be used.
22+
23+
Disables tqdm in headless CI/CD environments to avoid threading deadlocks
24+
that occur when tqdm's monitor thread interacts with CZI file reading
25+
on Linux systems.
26+
27+
Returns:
28+
bool: True if tqdm should be used, False otherwise.
29+
"""
30+
if os.environ.get("CI") == "true":
31+
return False
32+
if os.environ.get("GITHUB_ACTIONS") == "true":
33+
return False
34+
if os.environ.get("TQDM_DISABLE") == "1":
35+
return False
36+
if os.environ.get("QT_QPA_PLATFORM") == "offscreen":
37+
return False
38+
return True
39+
40+
41+
# Import tqdm based on environment
42+
if _should_use_tqdm():
43+
try:
44+
from tqdm import tqdm
45+
from tqdm.contrib.itertools import product
46+
except ImportError:
47+
def tqdm(x, *args, **kwargs):
48+
return x
49+
product = itertools.product
50+
else:
51+
def tqdm(x, *args, **kwargs):
52+
return x
53+
product = itertools.product
54+
1655
from pylibCZIrw import czi as pyczi
1756
from aicspylibczi import CziFile
1857
from czitools.metadata_tools import czi_metadata as czimd
@@ -23,8 +62,6 @@
2362
import dask
2463
import dask.delayed
2564
import os
26-
from tqdm import tqdm
27-
from tqdm.contrib.itertools import product
2865
import tempfile
2966
import shutil
3067
from czitools.utils import logging_tools

src/czitools/utils/planetable.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,43 @@
1616
import numpy as np
1717
from pathlib import Path
1818
import dateutil.parser as dt
19-
from tqdm.contrib.itertools import product
2019
from typing import Dict, Tuple, Any, Union, Optional
2120
import validators
2221
from aicspylibczi import CziFile
2322
from czitools.utils import logging_tools
2423

24+
25+
def _should_use_tqdm() -> bool:
26+
"""
27+
Determine if tqdm progress bars should be used.
28+
29+
Disables tqdm in headless CI/CD environments to avoid threading deadlocks
30+
that occur when tqdm's monitor thread interacts with CZI file reading
31+
on Linux systems.
32+
33+
Returns:
34+
bool: True if tqdm should be used, False otherwise.
35+
"""
36+
if os.environ.get("CI") == "true":
37+
return False
38+
if os.environ.get("GITHUB_ACTIONS") == "true":
39+
return False
40+
if os.environ.get("TQDM_DISABLE") == "1":
41+
return False
42+
if os.environ.get("QT_QPA_PLATFORM") == "offscreen":
43+
return False
44+
return True
45+
46+
47+
# Import product based on environment
48+
if _should_use_tqdm():
49+
try:
50+
from tqdm.contrib.itertools import product
51+
except ImportError:
52+
from itertools import product
53+
else:
54+
from itertools import product
55+
2556
logger = logging_tools.set_logging()
2657

2758

0 commit comments

Comments
 (0)