(
code: str,
timeout: float,
wait_after_kill=2.0,
minimum_free_ram_bytes=100_000_000,
log=True,
)
| 200 | |
| 201 | |
| 202 | def python_exec_sync( |
| 203 | code: str, |
| 204 | timeout: float, |
| 205 | wait_after_kill=2.0, |
| 206 | minimum_free_ram_bytes=100_000_000, |
| 207 | log=True, |
| 208 | ) -> str: |
| 209 | global ipython_shell |
| 210 | with io.StringIO() as file: |
| 211 | t = InterruptibleThread(target=worker, args=[code, file, timeout, log]) |
| 212 | t.start() |
| 213 | |
| 214 | started_waiting = time.time() |
| 215 | n_wait_steps = 0 |
| 216 | |
| 217 | # Go until timeout reached or memory cap reached |
| 218 | ExceptionClass = PythonExecTimeoutException |
| 219 | while t.is_alive() and time.time() - started_waiting < timeout: |
| 220 | cur_bytes = get_available_ram_bytes() |
| 221 | if cur_bytes < minimum_free_ram_bytes: |
| 222 | ExceptionClass = PythonExecOutOfMemoryException |
| 223 | ipython_shell = InteractiveShell.instance() |
| 224 | break |
| 225 | time.sleep(0.05) |
| 226 | n_wait_steps += 1 |
| 227 | if n_wait_steps % 80 == 0: |
| 228 | print( |
| 229 | f"python exec still running after {round(time.time()-started_waiting)} seconds {cur_bytes:,} bytes free", |
| 230 | # file=stderr, |
| 231 | ) |
| 232 | |
| 233 | # Try to kill it until we succeed or wait_after_kill exceeded |
| 234 | started_waiting = time.time() |
| 235 | gave_up = False |
| 236 | while t.is_alive(): |
| 237 | t.raiseException(ExceptionClass) |
| 238 | time.sleep(0.05) |
| 239 | if time.time() - started_waiting > wait_after_kill: |
| 240 | gave_up = True |
| 241 | break |
| 242 | |
| 243 | result = file.getvalue() |
| 244 | ansi_escape = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])") |
| 245 | result_cleaned = re.sub( |
| 246 | r"(^|\n)(Out|In)\[[0-9]+\]: ", r"\1", ansi_escape.sub("", result) |
| 247 | ) |
| 248 | if gave_up: |
| 249 | result_cleaned += "\nExecException: python exec timed out but could not be killed and is still going in the background" |
| 250 | |
| 251 | # "fix" ipython bug? causing error formatting exception |
| 252 | if ( |
| 253 | "Unexpected exception formatting exception. Falling back to standard exception" |
| 254 | in result_cleaned |
| 255 | ): |
| 256 | result_cleaned = result_cleaned.split( |
| 257 | "During handling of the above exception, another exception occurred" |
| 258 | )[0].replace( |
| 259 | "Unexpected exception formatting exception. Falling back to standard exception", |
nothing calls this directly
no test coverage detected