Reputation: 3002
I'm writing a grading robot for a Python programming class, and the students' submissions may loop infinitely. I want to sandbox a shell call to their program so that it can't run longer than a specific amount of time. I'd like to run, say,
restrict --msec=100 --default=-1 python -c "while True: pass"
and have it return -1 if the program runs longer than 100ms, and otherwise return the value of the executed expression (in this case, the output of the python program)
Does Python support this internally? I'm also writing the grading robot in Perl, so I could use some Perl module wrapped around the call to the shell script.
Upvotes: 2
Views: 587
Reputation: 879859
Use apply_async to call the student's function, (foo
in the example below). Use the get method with a timeout to get the result if it returns in 0.1 seconds or less, otherwise get
raise a TimeoutError:
import multiprocessing as mp
import time
import sys
def foo(x):
time.sleep(x)
return x*x
pool = mp.Pool(1)
for x in (0.01, 1.0):
try:
result = pool.apply_async(foo, args = (x,)).get(timeout = 0.1)
except KeyboardInterrupt:
pool.terminate()
sys.exit("Cancelled")
except mp.TimeoutError:
print('Timed out')
else:
print "Result: {r}".format(r = result)
Or, if the student submits a script instead of function, then you could use jcollado's Command
class.
Upvotes: 3
Reputation: 391872
The standard approach is to do the following.
Create a subprocess which runs the student's program in it's own Python instance.
Wait for a time.
If the student subprocess exits, good.
If the subprocess has not exited, you need to kill it.
You'll be happiest downloading the psutil module which allows each status checking of the subprocess.
Upvotes: 0