Skip to content

Commit ff49de3

Browse files
Use standard thread library (#580)
* Use standard thread library * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update shared.py * Update executor.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * clean up * fixes * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * ignore type warnings * more test fixes * another fix * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * more fixes * try to fix old version * Fix python 3.10 issue --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent c037c78 commit ff49de3

File tree

12 files changed

+70
-103
lines changed

12 files changed

+70
-103
lines changed

executorlib/base/executor.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
from concurrent.futures import (
77
Future,
88
)
9+
from threading import Thread
910
from typing import Callable, Optional, Union
1011

1112
from executorlib.standalone.inputcheck import check_resource_dict
1213
from executorlib.standalone.queue import cancel_items_in_queue
1314
from executorlib.standalone.serialize import cloudpickle_register
14-
from executorlib.standalone.thread import RaisingThread
1515

1616

1717
class ExecutorBase(FutureExecutor):
@@ -29,7 +29,7 @@ def __init__(self, max_cores: Optional[int] = None):
2929
cloudpickle_register(ind=3)
3030
self._max_cores = max_cores
3131
self._future_queue: Optional[queue.Queue] = queue.Queue()
32-
self._process: Optional[Union[RaisingThread, list[RaisingThread]]] = None
32+
self._process: Optional[Union[Thread, list[Thread]]] = None
3333

3434
@property
3535
def info(self) -> Optional[dict]:
@@ -40,13 +40,13 @@ def info(self) -> Optional[dict]:
4040
Optional[dict]: Information about the executor.
4141
"""
4242
if self._process is not None and isinstance(self._process, list):
43-
meta_data_dict = self._process[0].get_kwargs().copy()
43+
meta_data_dict = self._process[0]._kwargs.copy() # type: ignore
4444
if "future_queue" in meta_data_dict:
4545
del meta_data_dict["future_queue"]
4646
meta_data_dict["max_workers"] = len(self._process)
4747
return meta_data_dict
4848
elif self._process is not None:
49-
meta_data_dict = self._process.get_kwargs().copy()
49+
meta_data_dict = self._process._kwargs.copy() # type: ignore
5050
if "future_queue" in meta_data_dict:
5151
del meta_data_dict["future_queue"]
5252
return meta_data_dict
@@ -138,13 +138,13 @@ def shutdown(self, wait: bool = True, *, cancel_futures: bool = False):
138138
cancel_items_in_queue(que=self._future_queue)
139139
if self._process is not None and self._future_queue is not None:
140140
self._future_queue.put({"shutdown": True, "wait": wait})
141-
if wait and isinstance(self._process, RaisingThread):
141+
if wait and isinstance(self._process, Thread):
142142
self._process.join()
143143
self._future_queue.join()
144144
self._process = None
145145
self._future_queue = None
146146

147-
def _set_process(self, process: RaisingThread):
147+
def _set_process(self, process: Thread):
148148
"""
149149
Set the process for the executor.
150150

executorlib/cache/executor.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
from threading import Thread
23
from typing import Callable, Optional
34

45
from executorlib.base.executor import ExecutorBase
@@ -15,7 +16,6 @@
1516
check_max_workers_and_cores,
1617
check_nested_flux_executor,
1718
)
18-
from executorlib.standalone.thread import RaisingThread
1919

2020
try:
2121
from executorlib.cache.queue_spawner import execute_with_pysqa
@@ -64,7 +64,7 @@ def __init__(
6464
cache_directory_path = os.path.abspath(cache_directory)
6565
os.makedirs(cache_directory_path, exist_ok=True)
6666
self._set_process(
67-
RaisingThread(
67+
Thread(
6868
target=execute_tasks_h5,
6969
kwargs={
7070
"future_queue": self._future_queue,

executorlib/cache/shared.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,10 @@ def execute_tasks_h5(
115115
]
116116
else:
117117
if len(future_wait_key_lst) > 0:
118-
raise ValueError(
119-
"Future objects are not supported as input if disable_dependencies=True."
118+
task_dict["future"].set_exception(
119+
ValueError(
120+
"Future objects are not supported as input if disable_dependencies=True."
121+
)
120122
)
121123
task_dependent_lst = []
122124
process_dict[task_key] = execute_function(

executorlib/interactive/executor.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from concurrent.futures import Future
2+
from threading import Thread
23
from typing import Any, Callable, Optional
34

45
from executorlib.base.executor import ExecutorBase
@@ -8,7 +9,6 @@
89
generate_nodes_and_edges,
910
generate_task_hash,
1011
)
11-
from executorlib.standalone.thread import RaisingThread
1212

1313

1414
class ExecutorWithDependencies(ExecutorBase):
@@ -41,7 +41,7 @@ def __init__(
4141
) -> None:
4242
super().__init__(max_cores=max_cores)
4343
self._set_process(
44-
RaisingThread(
44+
Thread(
4545
target=execute_tasks_with_dependencies,
4646
kwargs={
4747
# Executor Arguments

executorlib/interactive/shared.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import time
66
from asyncio.exceptions import CancelledError
77
from concurrent.futures import Future, TimeoutError
8+
from threading import Thread
89
from time import sleep
910
from typing import Any, Callable, Optional, Union
1011

@@ -20,7 +21,6 @@
2021
)
2122
from executorlib.standalone.interactive.spawner import BaseSpawner, MpiExecSpawner
2223
from executorlib.standalone.serialize import serialize_funct_h5
23-
from executorlib.standalone.thread import RaisingThread
2424

2525

2626
class ExecutorBroker(ExecutorBase):
@@ -89,7 +89,7 @@ def shutdown(self, wait: bool = True, *, cancel_futures: bool = False):
8989
self._process = None
9090
self._future_queue = None
9191

92-
def _set_process(self, process: list[RaisingThread]): # type: ignore
92+
def _set_process(self, process: list[Thread]): # type: ignore
9393
"""
9494
Set the process for the executor.
9595
@@ -149,7 +149,7 @@ def __init__(
149149
executor_kwargs["queue_join_on_shutdown"] = False
150150
self._set_process(
151151
process=[
152-
RaisingThread(
152+
Thread(
153153
target=execute_parallel_tasks,
154154
kwargs=executor_kwargs,
155155
)
@@ -205,7 +205,7 @@ def __init__(
205205
executor_kwargs["max_cores"] = max_cores
206206
executor_kwargs["max_workers"] = max_workers
207207
self._set_process(
208-
RaisingThread(
208+
Thread(
209209
target=execute_separate_tasks,
210210
kwargs=executor_kwargs,
211211
)
@@ -363,17 +363,18 @@ def execute_tasks_with_dependencies(
363363
):
364364
future_lst, ready_flag = _get_future_objects_from_input(task_dict=task_dict)
365365
exception_lst = _get_exception_lst(future_lst=future_lst)
366-
if len(exception_lst) > 0:
367-
task_dict["future"].set_exception(exception_lst[0])
368-
elif len(future_lst) == 0 or ready_flag:
369-
# No future objects are used in the input or all future objects are already done
370-
task_dict["args"], task_dict["kwargs"] = _update_futures_in_input(
371-
args=task_dict["args"], kwargs=task_dict["kwargs"]
372-
)
373-
executor_queue.put(task_dict)
374-
else: # Otherwise add the function to the wait list
375-
task_dict["future_lst"] = future_lst
376-
wait_lst.append(task_dict)
366+
if not _get_exception(future_obj=task_dict["future"]):
367+
if len(exception_lst) > 0:
368+
task_dict["future"].set_exception(exception_lst[0])
369+
elif len(future_lst) == 0 or ready_flag:
370+
# No future objects are used in the input or all future objects are already done
371+
task_dict["args"], task_dict["kwargs"] = _update_futures_in_input(
372+
args=task_dict["args"], kwargs=task_dict["kwargs"]
373+
)
374+
executor_queue.put(task_dict)
375+
else: # Otherwise add the function to the wait list
376+
task_dict["future_lst"] = future_lst
377+
wait_lst.append(task_dict)
377378
future_queue.task_done()
378379
elif len(wait_lst) > 0:
379380
number_waiting = len(wait_lst)
@@ -589,7 +590,7 @@ def _submit_function_to_separate_process(
589590
"init_function": None,
590591
}
591592
)
592-
process = RaisingThread(
593+
process = Thread(
593594
target=execute_parallel_tasks,
594595
kwargs=task_kwargs,
595596
)
@@ -610,14 +611,13 @@ def _execute_task(
610611
future_queue (Queue): Queue for receiving new tasks.
611612
"""
612613
f = task_dict.pop("future")
613-
if f.set_running_or_notify_cancel():
614+
if not f.done() and f.set_running_or_notify_cancel():
614615
try:
615616
f.set_result(interface.send_and_receive_dict(input_dict=task_dict))
616617
except Exception as thread_exception:
617618
interface.shutdown(wait=True)
618619
future_queue.task_done()
619620
f.set_exception(exception=thread_exception)
620-
raise thread_exception
621621
else:
622622
future_queue.task_done()
623623

executorlib/standalone/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
interface_shutdown,
88
)
99
from executorlib.standalone.interactive.spawner import MpiExecSpawner
10-
from executorlib.standalone.thread import RaisingThread
1110

1211
__all__ = [
1312
"SocketInterface",
@@ -16,6 +15,5 @@
1615
"interface_send",
1716
"interface_shutdown",
1817
"interface_receive",
19-
"RaisingThread",
2018
"MpiExecSpawner",
2119
]

executorlib/standalone/thread.py

Lines changed: 0 additions & 42 deletions
This file was deleted.

tests/test_cache_executor_serial.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
from queue import Queue
44
import shutil
55
import unittest
6+
from threading import Thread
67

78
from executorlib.cache.subprocess_spawner import (
89
execute_in_subprocess,
910
terminate_subprocess,
1011
)
11-
from executorlib.standalone.thread import RaisingThread
1212

1313
try:
1414
from executorlib.cache.executor import FileExecutor, create_file_executor
@@ -57,7 +57,8 @@ def test_executor_dependence_error(self):
5757
with FileExecutor(
5858
execute_function=execute_in_subprocess, disable_dependencies=True
5959
) as exe:
60-
exe.submit(my_funct, 1, b=exe.submit(my_funct, 1, b=2))
60+
fs = exe.submit(my_funct, 1, b=exe.submit(my_funct, 1, b=2))
61+
fs.result()
6162

6263
def test_executor_working_directory(self):
6364
cwd = os.path.join(os.path.dirname(__file__), "executables")
@@ -81,7 +82,7 @@ def test_executor_function(self):
8182
)
8283
cache_dir = os.path.abspath("cache")
8384
os.makedirs(cache_dir, exist_ok=True)
84-
process = RaisingThread(
85+
process = Thread(
8586
target=execute_tasks_h5,
8687
kwargs={
8788
"future_queue": q,
@@ -122,7 +123,7 @@ def test_executor_function_dependence_kwargs(self):
122123
)
123124
cache_dir = os.path.abspath("cache")
124125
os.makedirs(cache_dir, exist_ok=True)
125-
process = RaisingThread(
126+
process = Thread(
126127
target=execute_tasks_h5,
127128
kwargs={
128129
"future_queue": q,
@@ -163,7 +164,7 @@ def test_executor_function_dependence_args(self):
163164
)
164165
cache_dir = os.path.abspath("cache")
165166
os.makedirs(cache_dir, exist_ok=True)
166-
process = RaisingThread(
167+
process = Thread(
167168
target=execute_tasks_h5,
168169
kwargs={
169170
"future_queue": q,

0 commit comments

Comments
 (0)