All checks were successful
Publish documentation / publish (push) Successful in 51s
Check / Test on Python 3.10 (push) Successful in 1m1s
Check / Lint, format & type checks (push) Successful in 1m9s
Check / Test on Python 3.11 (push) Successful in 51s
Check / Test on Python 3.12 (push) Successful in 58s
Check / Test on Python 3.13 (push) Successful in 55s
76 lines
2.4 KiB
Python
76 lines
2.4 KiB
Python
import multiprocessing as mp
|
|
import queue
|
|
import traceback
|
|
from typing import Dict, Iterable, List, TypeVar, Union
|
|
|
|
from ..chunk import chunk
|
|
from ..logger.get_logger import get_logger
|
|
from .map_result import MapResult
|
|
from .worker_exception import WorkerException
|
|
|
|
logger = get_logger("parallel_map")
|
|
|
|
T = TypeVar("T")
|
|
V = TypeVar("V")
|
|
|
|
|
|
def manage_communication(
|
|
*,
|
|
input_values: Iterable[T],
|
|
chunk_size: int,
|
|
input_queue: Union[mp.Queue, queue.Queue],
|
|
output_queue: Union[mp.Queue, queue.Queue],
|
|
unordered: bool,
|
|
ignore_exceptions: bool,
|
|
) -> Iterable[V]:
|
|
chunks = iter(chunk(enumerate(input_values), chunk_size=chunk_size))
|
|
indexed_results: Dict[int, V] = {}
|
|
next_output_index = 0
|
|
read_input_length = 0
|
|
is_iteration_over = False
|
|
|
|
while not is_iteration_over or next_output_index < read_input_length:
|
|
if not is_iteration_over:
|
|
try:
|
|
next_chunk = next(chunks)
|
|
input_queue.put(next_chunk)
|
|
read_input_length += len(next_chunk)
|
|
except StopIteration:
|
|
is_iteration_over = True
|
|
except Exception as e:
|
|
if ignore_exceptions:
|
|
logger.error(
|
|
f"""Exception {e} encountered in input, traceback:\n{
|
|
traceback.format_exc()
|
|
}"""
|
|
)
|
|
else:
|
|
raise
|
|
|
|
try:
|
|
result_chunk: List[MapResult] = output_queue.get_nowait()
|
|
for r in result_chunk:
|
|
if r.exception is not None:
|
|
if ignore_exceptions:
|
|
logger.error(
|
|
f"""Exception {
|
|
r.exception
|
|
} encountered in worker, traceback:\n{r.worker_traceback}"""
|
|
)
|
|
else:
|
|
raise WorkerException(r.exception)
|
|
|
|
if unordered:
|
|
|
|
yield r.value
|
|
next_output_index += 1
|
|
else:
|
|
indexed_results[r.order] = r.value
|
|
|
|
if not unordered:
|
|
while next_output_index in indexed_results:
|
|
yield indexed_results[next_output_index]
|
|
del indexed_results[next_output_index]
|
|
next_output_index += 1
|
|
except queue.Empty:
|
|
pass
|