Установка тайм-аута при использовании функции os.system

Во-первых, я хотел бы сказать, что я только начинаю изучать python, и я хочу выполнить команду maven внутри своего скрипта python (см. Частичный код ниже)

os.system("mvn surefire:test")

Но, к сожалению, иногда время ожидания этой команды истекает, поэтому я хочу знать, как установить порог тайм-аута для управления этой командой.

То есть, если время выполнения превышает X секунд, программа пропустит команду.

Более того, может ли другое полезное решение решить мою проблему? Заранее спасибо!


person Yongfeng    schedule 12.12.2016    source источник
comment
Возможный дубликат убийства скрипта, запущенного в процессе через ОС .system ()   -  person Alessandro Da Rugna    schedule 12.12.2016


Ответы (2)


вместо этого используйте модуль подпроцесса. Используя список и придерживаясь значения по умолчанию shell=False, мы можем просто убить процесс, когда истечет время ожидания.

p = subprocess.Popen(['mvn', 'surfire:test'])
try:
    p.wait(my_timeout)
except subprocess.TimeoutExpired:
    p.kill()
person tdelaney    schedule 12.12.2016
comment
Большое спасибо, и мне просто интересно, могу ли я заменить код subprocess.Popen (['mvn', 'surefire: test']) на subprocess.Popen ('mvn surefire: test', shell = True) - person Yongfeng; 12.12.2016
comment
Ваш ответ полностью решил мою ПРОБЛЕМУ, я просто трачу время на maven, так как подпроцесс может мне помочь в конце. - person Yongfeng; 12.12.2016
comment
Но здесь возникает побочный эффект: подпроцесс уничтожается, в то время как другой процесс Java(TM) Platform SE binary не может быть уничтожен. Итак, что мне делать и как убить этот процесс, я использовал p.pid и os.getpid () для получения идентификатора процесса. Но просто не могу найти pid Java(TM) Platform SE binary - person Yongfeng; 12.12.2016
comment
Это усложняется ... когда промежуточный процесс создает дочерний процесс, трудно понять, что завершить. psutil может помочь. Вот пример: stackoverflow.com/a/4229404/642070 - person tdelaney; 12.12.2016
comment
Я использую python3.5.0, я нашел этот документ по ссылке , и пробовал использовать некоторые функции, такие как subprocess.run, subprocess.call, но все время терпел неудачу, возможно, мне стоит попробовать psutil. - person Yongfeng; 13.12.2016
comment
Да, иногда программа, которую вы запускаете, является просто посредником, который запускает другую программу и закрывается. Процесс, о котором вы знаете, ушел, поэтому вы не можете его убить - person tdelaney; 13.12.2016

Простой ответ

os.system не поддерживает timeout.

вместо этого вы можете использовать подпроцесс Python 3, который поддерживает параметр 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)
person crifan    schedule 17.12.2020
comment
Это помогло. Спасибо! - person mjuanes; 25.06.2021