7

Firstly, I'd like to say I just begin to learn python, And I want to execute maven command inside my python script (see the partial code below)

os.system("mvn surefire:test")

But unfortunately, sometimes this command will time out, So I wanna to know how to set a timeout threshold to control this command.

That is to say, if the executing time is beyond X seconds, the program will skip the command.

What's more, can other useful solution deal with my problem? Thanks in advance!

Yongfeng
  • 345
  • 1
  • 3
  • 15
  • Possible duplicate of [Killing a script launched in a Process via os.system()](http://stackoverflow.com/questions/12321077/killing-a-script-launched-in-a-process-via-os-system) – Alessandro Da Rugna Dec 12 '16 at 08:29

3 Answers3

7

use the subprocess module instead. By using a list and sticking with the default shell=False, we can just kill the process when the timeout hits.

p = subprocess.Popen(['mvn', 'surfire:test'])
try:
    p.wait(my_timeout)
except subprocess.TimeoutExpired:
    p.kill()
Julian
  • 550
  • 1
  • 4
  • 16
tdelaney
  • 73,364
  • 6
  • 83
  • 116
  • Thanks very much, And I just wonder can I replace the code "subprocess.Popen(['mvn', 'surefire:test'])" with "subprocess.Popen('mvn surefire:test', shell = True)" – Yongfeng Dec 12 '16 at 06:20
  • Your answer is completely solved my PROBLEM, I just waste some time on maven, since the subprocess can help me in the end. – Yongfeng Dec 12 '16 at 06:36
  • But here comes the side-effect, the sub-process is killed while another process `Java(TM) Platform SE binary` cannot be killed. So what should I do and how can I kill this process, I have used p.pid and os.getpid() to get the process id. But just cannot find the pid of `Java(TM) Platform SE binary` – Yongfeng Dec 12 '16 at 11:04
  • It gets complicated... when an intermediate process creates a grandchild process, its hard to figure out what to terminate. `psutil` can help. Here is an example: http://stackoverflow.com/a/4229404/642070 – tdelaney Dec 12 '16 at 17:51
  • I am using python3.5.0, I found this document [link](https://docs.python.org/3/library/subprocess.html#subprocess.run), and have tried some functions such as **subprocess.run**, **subprocess.call**, but failed all the time, maybe I should try `psutil`. – Yongfeng Dec 13 '16 at 03:17
  • Yeah, sometimes the program you start is just an intermediary that starts another program and exits. The process you know about is gone so you can't kill it – tdelaney Dec 13 '16 at 16:15
3

Also, you can use in terminal timeout:

Do like that:

import os

os.system('timeout 5s [Type Command Here]')

Also, you can use s, m, h, d for second, min, hours, day. You can send different signal to command. If you want to learn more, see at: https://linuxize.com/post/timeout-command-in-linux/

WitBlack
  • 37
  • 4
2

Simple answer

os.system not support timeout.

you can use Python 3's subprocess instead, which support timeout parameter

such as:

yourCommand = "mvn surefire:test"
timeoutSeconds = 5
subprocess.check_output(yourCommand, shell=True, timeout=timeoutSeconds)

Detailed Explanation

in further, I have encapsulate to a function getCommandOutput for you:

def getCommandOutput(consoleCommand, consoleOutputEncoding="utf-8", timeout=2):
    """get command output from terminal


    Args:
        consoleCommand (str): console/terminal command string
        consoleOutputEncoding (str): console output encoding, default is utf-8
        timeout (int): wait max timeout for run console command
    Returns:
        console output (str)
    Raises:
    """
    # print("getCommandOutput: consoleCommand=%s" % consoleCommand)
    isRunCmdOk = False
    consoleOutput = ""
    try:
        # consoleOutputByte = subprocess.check_output(consoleCommand)


        consoleOutputByte = subprocess.check_output(consoleCommand, shell=True, timeout=timeout)


        # commandPartList = consoleCommand.split(" ")
        # print("commandPartList=%s" % commandPartList)
        # consoleOutputByte = subprocess.check_output(commandPartList)
        # print("type(consoleOutputByte)=%s" % type(consoleOutputByte)) # <class 'bytes'>
        # print("consoleOutputByte=%s" % consoleOutputByte) # b'640x360\n'


        consoleOutput = consoleOutputByte.decode(consoleOutputEncoding) # '640x360\n'
        consoleOutput = consoleOutput.strip() # '640x360'
        isRunCmdOk = True
    except subprocess.CalledProcessError as callProcessErr:
        cmdErrStr = str(callProcessErr)
        print("Error %s for run command %s" % (cmdErrStr, consoleCommand))


    # print("isRunCmdOk=%s, consoleOutput=%s" % (isRunCmdOk, consoleOutput))
    return isRunCmdOk, consoleOutput

demo :

isRunOk, cmdOutputStr = getCommandOutput("mvn surefire:test", timeout=5)
crifan
  • 12,947
  • 1
  • 71
  • 56