使用os.system函数时如何设置超时时间

7

首先,我想说我刚开始学习Python,我想在我的Python脚本中执行maven命令(见下面的部分代码)

os.system("mvn surefire:test")

但不幸的是,有时这个命令会超时,所以我想知道如何设置超时阈值来控制这个命令。

也就是说,如果执行时间超过X秒,程序将跳过该命令

此外,还有其他有用的解决方案可以解决我的问题吗?提前感谢!


可能是Killing a script launched in a Process via os.system()的重复问题。 - Alessandro Da Rugna
3个回答

8
请使用subprocess模块代替。通过使用列表并坚持默认的shell=False,当超时发生时,我们可以直接终止该进程。
p = subprocess.Popen(['mvn', 'surfire:test'])
try:
    p.wait(my_timeout)
except subprocess.TimeoutExpired:
    p.kill()

非常感谢,我只是想知道是否可以用 "subprocess.Popen('mvn surefire:test', shell = True)" 替换代码 "subprocess.Popen(['mvn', 'surefire:test'])"。 - Yongfeng
你的答案完全解决了我的问题,我只是在 Maven 上浪费了一些时间,因为 subprocess 最终可以帮助我。 - Yongfeng
但这里有一个副作用,子进程被杀死,而另一个进程“Java(TM) Platform SE binary”无法被杀死。那么我应该怎么办?如何杀死这个进程,我已经使用了p.pid和os.getpid()来获取进程ID。但是就是找不到“Java(TM) Platform SE binary”的PID。 - Yongfeng
当一个中间进程创建了一个孙子进程时,要弄清楚该终止哪个进程就变得复杂了。psutil可以帮助解决这个问题。以下是一个示例:https://dev59.com/E3M_5IYBdhLWcg3wyWWt#4229404 - tdelaney
我正在使用Python3.5.0,我发现了这个文档链接,并尝试了一些函数,如subprocess.runsubprocess.call,但每次都失败了,也许我应该尝试psutil - Yongfeng
有时候,你启动的程序只是一个中介,它会启动另一个程序并退出。你知道的进程已经消失了,所以你无法终止它。 - tdelaney

3

简单回答

os.system 不支持 timeout 参数。

您可以使用 Python 3subprocess 替代,它支持 timeout 参数。

例如:

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

详细解释

进一步地,我已经为您封装了一个函数getCommandOutput

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

演示:

isRunOk, cmdOutputStr = getCommandOutput("mvn surefire:test", timeout=5)

3

此外,您还可以在终端中使用“timeout”命令:

像这样进行操作:

import os

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

此外,您可以使用 s、m、h、d 表示秒、分、小时和天。您可以向命令发送不同的信号。如果您想了解更多信息,请参见: https://linuxize.com/post/timeout-command-in-linux/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接