|
| 1 | +import subprocess |
| 2 | +import time |
| 3 | +from enum import Enum |
| 4 | + |
| 5 | + |
| 6 | +class ExecStatus(Enum): |
| 7 | + NORMAL = "NORMAL" |
| 8 | + TLE = "TLE" |
| 9 | + RE = "RE" |
| 10 | + |
| 11 | + |
| 12 | +class ExecResult: |
| 13 | + |
| 14 | + def __init__(self, status: ExecStatus, output: str = None, stderr: str = None, elapsed_sec: float = None): |
| 15 | + self.status = status |
| 16 | + self.output = output |
| 17 | + self.stderr = stderr |
| 18 | + |
| 19 | + if elapsed_sec is not None: |
| 20 | + self.elapsed_ms = int(elapsed_sec * 1000 + 0.5) |
| 21 | + else: |
| 22 | + self.elapsed_ms = None |
| 23 | + |
| 24 | + def is_correct_output(self, answer_text): |
| 25 | + return self.status == ExecStatus.NORMAL and answer_text == self.output |
| 26 | + |
| 27 | + def has_stderr(self): |
| 28 | + return len(self.stderr) > 0 |
| 29 | + |
| 30 | + |
| 31 | +def run_program(exec_file: str, input_file: str, timeout_sec: int, args=None, current_working_dir: str = None) -> ExecResult: |
| 32 | + if args is None: |
| 33 | + args = [] |
| 34 | + try: |
| 35 | + elapsed_sec = -time.time() |
| 36 | + proc = subprocess.run( |
| 37 | + [exec_file] + args, stdin=open(input_file, 'r'), universal_newlines=True, timeout=timeout_sec, |
| 38 | + stdout=subprocess.PIPE, |
| 39 | + stderr=subprocess.PIPE, |
| 40 | + cwd=current_working_dir |
| 41 | + ) |
| 42 | + |
| 43 | + if proc.returncode == 0: |
| 44 | + code = ExecStatus.NORMAL |
| 45 | + else: |
| 46 | + code = ExecStatus.RE |
| 47 | + |
| 48 | + elapsed_sec += time.time() |
| 49 | + return ExecResult(code, proc.stdout, proc.stderr, elapsed_sec=elapsed_sec) |
| 50 | + except subprocess.TimeoutExpired as e: |
| 51 | + return ExecResult(ExecStatus.TLE, e.stdout, e.stderr) |
| 52 | + except subprocess.CalledProcessError as e: |
| 53 | + return ExecResult(ExecStatus.RE, e.stdout, e.stderr) |
0 commit comments