1

I've got this code

    r = x.run("prog", ["-4"], ['\tab \t cd\n', ' \t ab cd \n', '\ta\b\b\b\tb\n'])

Where "prog" is the name of an executable c file,"-4" is a command line argument used by "prog" and '\tab \t cd\n', ' \t ab cd \n', '\ta\b\b\b\tb\n' is the input text for the file "prog"

My run function is...

    def run(self, prog, args, input):
    global debug
    result = None
    prog = os.path.join(".",prog)
    command = [prog] + args
    self.createFile(CompileAndExecute.stdinName, input)
    cwd = os.getcwd()
    os.chdir(self.tmpdir)
    stream0 = open(CompileAndExecute.stdinName, "r")
    stream1 = open(CompileAndExecute.stdoutName, "w")
    stream2 = open(CompileAndExecute.stderrName, "w")
    p = None

    try:
        p = subprocess.call(command,
            stdin=stream0, stdout=stream1, stderr=stream2)
    except:
        result = sys.exc_info()
        if p != None:
            p.kill()
    finally:
        stream0.close()
        stream1.close()
        stream2.close()
        os.remove(CompileAndExecute.stdinName)
    os.chdir(cwd)
    return result

I want to add another parameter inside my run function, called timeout. Basically, I want it so that if my run function is taking longer than 5 seconds, i'll call Sys.exit(1) and end it there.

The proper call of my run function, with the added timeout parameter, would be

r = x.run("prog", ["-4"], ['\tab \t cd\n', ' \t ab cd \n', '\ta\b\b\b\tb\n'], 5)

The general idea of my complete code, all of it is not here, is to compile and execute a C file and check if its output is what it should be.

I was recommended to See section 17.5.1 of the Python3 library documentation for information on how to implement a timeout, but was not able to understand how to. And I tried some solutions to similar questions, but it didn't work out.

Any help?

EDIT: More info on the run function..

run(self, prog,args=[],input=[])

The prog argument is a string which specified the name of the executable file in the temporary directory. The args argument contains a list of strings which are to be used as command line arguments for the program named by prog. The run method executes the program, supplying the command line arguments. If the program, while running, reads from its standard input then that standard input is taken from the argument named input. The input argument is a list of strings; each string represents one line of text input to be read by the program. When the run method returns, the result is either None (for an apparently successful completion) or a string (which specifies a reason for the pro- gram not executing or not completing successfully). Whatever is returned by the function call, both the standard output stream and the standard error output stream should be checked.

CompileAndExecute is the class name that run is found in..

class CompileAndExecute:
"""The class provides methods for compiling and testing
a program in a temporary directory."""
stdoutName = ".stdout.txt"
stderrName = ".stderr.txt"
stdinName  = ".stdin.txt"

# constructor, creates temporary directory
def __init__(self, compiler):
    self.compiler = compiler
    self.tmpdir = tempfile.mkdtemp()

UPDATE: After some help, I'm getting syntax error

    def run(self, prog, args, input):
    global debug
    result = None
    prog = os.path.join(".",prog)
    command = [prog] + args
    self.createFile(CompileAndExecute.stdinName, input)
    cwd = os.getcwd()
    os.chdir(self.tmpdir)
    stream0 = open(CompileAndExecute.stdinName, "r")
    stream1 = open(CompileAndExecute.stdoutName, "w")
    stream2 = open(CompileAndExecute.stderrName, "w")
    p = None

    try:
        p = subprocess.call(command,
        stdin=stream0, stdout=stream1, stderr=stream2, timeout = 5)
        except subprocess.TimeoutExpired:
            sys.exit(1)
        except:
            result = sys.exc_info()
        if p != None:
            p.kill()
     finally:
        stream0.close()
        stream1.close()
        stream2.close()
        os.remove(CompileAndExecute.stdinName)
    os.chdir(cwd)
    return result

For the line of code in the above chunk, except subprocess.TimeoutExpired:

2
  • Are you using Python 3? Commented Jul 28, 2015 at 1:24
  • Yes, I am using Python 3 Commented Jul 28, 2015 at 1:25

1 Answer 1

2

For Python 3+ , you can use the timeout argument for subprocess.call , passing in the timeout you want to specify , and then if the timeout expires before the child process got terminated, subprocess would terminate the child process and raise subprocess.TimeoutExpired exception, which you can catch, and then call sys.exit(1) .

So in your code, you would do -

try:
    p = subprocess.call(command,
        stdin=stream0, stdout=stream1, stderr=stream2, timeout=5)
except subprocess.TimeoutExpired:
    import sys #don't need this here, if you have imported anywhere above.
    sys.exit(1)
except:
    result = sys.exc_info()
    if p != None:
        p.kill()

Also, the subprocess.call function returns the returncode, not the process itself, so trying to do p.kill() inside the except: does not do anything.

Demo -

import sys
try:
    subprocess.call(['python','a.py'],timeout=1)
except subprocess.TimeoutExpired:
    sys.exit(1)

Where a.py is a python script, that loops 100000 time.

Sign up to request clarification or add additional context in comments.

5 Comments

Ok, So I used the code you have in the first part of your answer, put it in word for word, but it still doesn't exit the function. The C file being run has an infinite loop inside of it. So I looked at the other part of your code, the demo, added timeout = 5 to my p= = subprocess.call(command, stdin=stream0, stdout=stream1, stderr=stream2), leaving me with p= subprocess.call(command, stdin=stream0, stdout=stream1, stderr=stream2, timeout = 5), and added the except subprocess.TimeoutExpired: sys.exit(1) but it still won't exit
Hmm, if you remove the try:except: block, is there any exception that is occurring? Can you please check.
SCRATCH THAT lol, I actually get an invalid syntax error on except subprocess.TimoutExpired:
You except is indented at the wrong position, indent it with try
HEY, Noob mistakes, I had bad indentation basically on my except.. haha it works now! Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.