py-adtools 0.1.7__py3-none-any.whl → 0.1.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of py-adtools might be problematic. Click here for more details.

adtools/evaluator.py CHANGED
@@ -8,9 +8,10 @@ Commercial use of this software or its derivatives requires prior written permis
8
8
  import multiprocessing
9
9
  import os
10
10
  import sys
11
+ import time
11
12
  from abc import ABC, abstractmethod
12
13
  from queue import Empty
13
- from typing import Any, Literal, Dict, Callable, List
14
+ from typing import Any, Literal, Dict, Callable, List, Tuple
14
15
  import psutil
15
16
  import traceback
16
17
 
@@ -22,6 +23,7 @@ class PyEvaluator(ABC):
22
23
  def __init__(
23
24
  self,
24
25
  exec_code: bool = True,
26
+ find_and_kill_children_evaluation_process: bool = False,
25
27
  debug_mode: bool = False,
26
28
  *,
27
29
  join_timeout_seconds: int = 10
@@ -33,11 +35,15 @@ class PyEvaluator(ABC):
33
35
  which will be passed to 'self.evaluate_program()'. Set this parameter to 'False' if you are going to
34
36
  evaluate a Python scripy. Note that if the parameter is set to 'False', the arguments 'callable_...'
35
37
  in 'self.evaluate_program()' will no longer be affective.
38
+ find_and_kill_children_evaluation_process: If using 'self.secure_evaluate', kill children processes
39
+ when they are terminated. Note that it is suggested to set to 'False' if the evaluation process
40
+ does not start new processes.
36
41
  debug_mode: Debug mode.
37
42
  join_timeout_seconds: Timeout in seconds to wait for the process to finish. Kill the process if timeout.
38
43
  """
39
44
  self.debug_mode = debug_mode
40
45
  self.exec_code = exec_code
46
+ self.find_and_kill_children_evaluation_process = find_and_kill_children_evaluation_process
41
47
  self.join_timeout_seconds = join_timeout_seconds
42
48
 
43
49
  @abstractmethod
@@ -66,11 +72,14 @@ class PyEvaluator(ABC):
66
72
  )
67
73
 
68
74
  def _kill_process_and_its_children(self, process: multiprocessing.Process):
69
- # Find all children processes
70
- try:
71
- parent = psutil.Process(process.pid)
72
- children_processes = parent.children(recursive=True)
73
- except psutil.NoSuchProcess:
75
+ if self.find_and_kill_children_evaluation_process:
76
+ # Find all children processes
77
+ try:
78
+ parent = psutil.Process(process.pid)
79
+ children_processes = parent.children(recursive=True)
80
+ except psutil.NoSuchProcess:
81
+ children_processes = []
82
+ else:
74
83
  children_processes = []
75
84
  # Terminate parent process
76
85
  process.terminate()
@@ -151,8 +160,9 @@ class PyEvaluator(ABC):
151
160
  timeout_seconds: int | float = None,
152
161
  redirect_to_devnull: bool = False,
153
162
  multiprocessing_start_method: Literal['default', 'auto', 'fork', 'spawn'] = 'auto',
163
+ get_evaluate_time=False,
154
164
  **kwargs
155
- ):
165
+ ) -> Any | Tuple[Any, float]:
156
166
  """Evaluate program in a new process. This enables timeout restriction and output redirection.
157
167
  Args:
158
168
  program: the program to be evaluated.
@@ -161,7 +171,11 @@ class PyEvaluator(ABC):
161
171
  multiprocessing_start_method: start a process using 'fork' or 'spawn'. If set to 'auto',
162
172
  the process will be started using 'fork' with Linux/macOS and 'spawn' with Windows.
163
173
  If set to 'default', there will be no changes to system default.
174
+ get_evaluate_time: get evaluation time for this program.
164
175
  **kwargs: additional keyword arguments to pass to 'evaluate_program'.
176
+ Returns:
177
+ Returns the evaluation results. If the 'get_evaluate_time' is True,
178
+ the return value will be (Results, Time).
165
179
  """
166
180
  if multiprocessing_start_method == 'auto':
167
181
  # Force macOS and Linux use 'fork' to generate new process
@@ -180,21 +194,28 @@ class PyEvaluator(ABC):
180
194
  args=(str(program), result_queue, redirect_to_devnull),
181
195
  kwargs=kwargs,
182
196
  )
197
+ evaluate_start_time = time.time()
183
198
  process.start()
184
199
 
185
200
  if timeout_seconds is not None:
186
201
  try:
187
202
  # Get the result in timeout seconds
188
203
  result = result_queue.get(timeout=timeout_seconds)
204
+ # Calculate the evaluate time
205
+ eval_time = time.time() - evaluate_start_time
189
206
  # After getting the result, terminate/kill the process
190
207
  self._kill_process_and_its_children(process)
191
208
  except Empty: # The queue is empty indicates a timeout
209
+ # Calculate the evaluate time
210
+ eval_time = time.time() - evaluate_start_time
192
211
  if self.debug_mode:
193
212
  print(f'DEBUG: the evaluation time exceeds {timeout_seconds}s.')
194
213
  # Terminate/kill all processes if timeout happens
195
214
  self._kill_process_and_its_children(process)
196
215
  result = None
197
216
  except Exception as e:
217
+ # Calculate the evaluate time
218
+ eval_time = time.time() - evaluate_start_time
198
219
  if self.debug_mode:
199
220
  print(f'DEBUG: evaluation failed with exception:\n{traceback.format_exc()}')
200
221
  # Terminate/kill all processes if meet exceptions
@@ -203,9 +224,12 @@ class PyEvaluator(ABC):
203
224
  else:
204
225
  # If there is no timeout limit, wait execution to finish
205
226
  result = result_queue.get()
227
+ # Calculate the evaluate time
228
+ eval_time = time.time() - evaluate_start_time
206
229
  # Terminate/kill all processes after evaluation
207
230
  self._kill_process_and_its_children(process)
208
- return result
231
+
232
+ return (result, eval_time) if get_evaluate_time else result
209
233
  except Exception as e:
210
234
  if self.debug_mode:
211
235
  print(traceback.format_exc())
adtools/evaluator_pool.py CHANGED
@@ -62,21 +62,23 @@ class EvaluatorExecutorPool:
62
62
  program: the program to be evaluated.
63
63
  timeout_seconds: return 'None' if the execution time exceeds 'timeout_seconds'.
64
64
  redirect_to_devnull: redirect any output to '/dev/null'.
65
- multiprocessing_start_method: start a process using 'fork' or 'spawn'.
65
+ multiprocessing_start_method: start a process using 'fork' or 'spawn'. If set to 'auto',
66
+ the process will be started using 'fork' with Linux/macOS and 'spawn' with Windows.
67
+ If set to 'default', there will be no changes to system default.
68
+ return_time: get evaluation time for this program.
66
69
  **kwargs: additional keyword arguments to pass to 'evaluate_program'.
70
+ Returns:
71
+ Returns the evaluation results. If the 'get_evaluate_time' is True,
72
+ the return value will be (Results, Time).
67
73
  """
68
- start_time = time.time()
69
74
  future = self.pool.submit(
70
75
  self.evaluator.secure_evaluate,
71
76
  program,
72
77
  timeout_seconds,
73
78
  redirect_to_devnull,
74
79
  multiprocessing_start_method,
80
+ return_time,
75
81
  **kwargs
76
82
  )
77
83
  res = future.result()
78
- duration = time.time() - start_time
79
- if return_time:
80
- return res, duration
81
- else:
82
- return res
84
+ return res
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: py-adtools
3
- Version: 0.1.7
3
+ Version: 0.1.8
4
4
  Summary: Useful tools for parsing and evaluating Python programs for LLM-based algorithm design.
5
5
  Home-page: https://github.com/RayZhhh/py-adtools
6
6
  Author: Rui Zhang
@@ -1,13 +1,13 @@
1
1
  adtools/__init__.py,sha256=kbxntZFeCcURiIypNOdMWyeKPdlzRsWOB-K7z6HNCsc,150
2
- adtools/evaluator.py,sha256=weA6zR1WyUE3f5pt7wQYF1ukmkA-e2kDLaogbDmG_Ig,9154
3
- adtools/evaluator_pool.py,sha256=v_NZibN4VI3STVUZt6ARdyoB4Z061xAefZlH8lkWsjE,2972
2
+ adtools/evaluator.py,sha256=A33E0HmLsIMtMbdjRmfPzck9gDodJc96gvXR0cL_SR0,10577
3
+ adtools/evaluator_pool.py,sha256=zfQ7DgAjpByqPM5SE1tRQT_HGXU5uwNntvguzrXaPEk,3258
4
4
  adtools/py_code.py,sha256=FZfkp-IZ4zpOjrWe6svKNJsQhVANaTTkE0l0mc4aMW8,14277
5
5
  adtools/lm/__init__.py,sha256=PZf5Lraly9rAWz-cxOSLCvZ9OZ4EI8aQEluetvNX8LM,146
6
6
  adtools/lm/lm_base.py,sha256=KtO7KTrrMW7oWN-BhncoIOsbOVQsSc-0gNCYtvR6Sog,1105
7
7
  adtools/lm/openai_api.py,sha256=LcfLkNOBrJTdsp0zcUjaCelIcQK5XknpHWrlB0S67_k,2390
8
8
  adtools/lm/vllm_server.py,sha256=BPZoTS77wNJDcJ_0FO2QFyZTf6WR0isYKMuTctqKEU8,12942
9
- py_adtools-0.1.7.dist-info/licenses/LICENSE,sha256=E5GGyecx3y5h2gcEGQloF-rDY9wbaef5IHjRsvtFbt8,1065
10
- py_adtools-0.1.7.dist-info/METADATA,sha256=952zQgrdHcpBYGmnYqfwlVFfMubvvSYixg-weIf4eWU,6386
11
- py_adtools-0.1.7.dist-info/WHEEL,sha256=lTU6B6eIfYoiQJTZNc-fyaR6BpL6ehTzU3xGYxn2n8k,91
12
- py_adtools-0.1.7.dist-info/top_level.txt,sha256=X2kKzmJFDAKR2FWCij5pfMG9pVVjVUomyl4e-1VLXIk,8
13
- py_adtools-0.1.7.dist-info/RECORD,,
9
+ py_adtools-0.1.8.dist-info/licenses/LICENSE,sha256=E5GGyecx3y5h2gcEGQloF-rDY9wbaef5IHjRsvtFbt8,1065
10
+ py_adtools-0.1.8.dist-info/METADATA,sha256=22hW8kcx1OxxlcedTDYIX1EzfB79pRYEtU3cXptveE8,6386
11
+ py_adtools-0.1.8.dist-info/WHEEL,sha256=lTU6B6eIfYoiQJTZNc-fyaR6BpL6ehTzU3xGYxn2n8k,91
12
+ py_adtools-0.1.8.dist-info/top_level.txt,sha256=X2kKzmJFDAKR2FWCij5pfMG9pVVjVUomyl4e-1VLXIk,8
13
+ py_adtools-0.1.8.dist-info/RECORD,,