Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Завершение программы в python

Автор вопроса: jackarazОтветов: 1

Привет, я внедрил ограничение по времени в свой код Python, который запускает код fortran с функцией. Однако я понял, что функция, которая накладывает ограничение по времени на другую функцию, не завершает код, а просто оставляет его в фоновом режиме и вместо этого пропускает. Что я хочу сделать, так это завершить код, когда он превысит ограниченное время. Вот код, который я использую для ограничения времени, взятый из здесь.

def timeout(func, args=(), kwargs={}, timeout_duration=15, default=1):
    import signal

    class TimeoutError(Exception):
        pass

    def handler(signum, frame):
        raise TimeoutError()

    # set the timeout handler
    signal.signal(signal.SIGALRM, handler)
    signal.alarm(timeout_duration)
    try:
        result = func(*args, **kwargs)
    except TimeoutError as exc:
        result = default
    finally:
        signal.alarm(0)

    return result

Я искал popen.terminate(), sys.exit() и atexit.register(), но не мог понять, как это будет работать с этим фрагментом кода, который я пытался добавить в части ниже, которую я показал в комментарии.

...
        result = func(*args, **kwargs)
    except TimeoutError as exc:
        result = default
#add the terminator
    finally:
...

ПРИМЕЧАНИЕ. Функция находится внутри цепочки циклов for, поэтому я не хочу убивать весь сеанс python, а просто хочу убить программу, которую запускает эта функция, которая является кодом fortran, и перейти к другому элементу в цепочке цикла for.

Часть ниже добавлена после некоторых комментариев и ответов:

Я попытался добавить SIGTERM с помощью popen.terminate(), однако он завершил весь сеанс python, который я просто хочу завершить текущий запущенный сеанс и перейти к другим элементам в цикле for. я сделал следующее:

...
    signal.signal(signal.SIGTERM, handler)
    signal.alarm(timeout_duration)
    try:
        result = func(*args, **kwargs)
    except TimeoutError as exc:
        result = default
        popen.terminate()
...
  • что вы подразумеваете под программой, которую запускает эта функция? Это внешний процесс, запущенный модулем subprocess? Существуют ли процессы-потомки? Процесс завершается, если вы отправляете сигнал SIGTERM? Какая у вас версия Python? Должно быть достаточно передать параметр timeout в process.wait() и вызвать process.terminate() по TimeoutError, если потомков нет и процесс завершается на SIGTERM. jfs 31.03.2016
  • @ J.F.Sebastian этот код запускает функцию, которая запускает код на фортране, который я хочу ограничить временем выполнения для сохранения из процессора. Все, что делает эта функция, это оставляет код fortran в фоновом режиме и переходит к другому элементу в цикле for, который накапливается в процессоре после 100 циклов, скажем, поэтому я хочу завершить сеанс, прежде чем перейти к другому элементу. Питон версии 2.7. jackaraz 01.04.2016
  • Возможно, связано: Выполнить команду в течение указанного времени, а затем прервать, если время превышается GingerPlusPlus 01.04.2016
  • @jackaraz снова, означает ли запуск кода на фортране, что вы запускаете внешний процесс, используя модуль subprocess? (Например, библиотека numpy выполняет большое количество кода на Фортране без запуска нового процесса). Чтобы ограничить количество одновременных процессов, см. этот ответ. jfs 01.04.2016
  • @ J.F.Sebastian да, я использую subprocess.check_output('./../bin/SPhenoUMSSM ../UMSSM/LH_out_'+mod+' > SPheno_log_'+mod, shell=True) в другой функции для запуска кода на фортране jackaraz 01.04.2016
  • @jackaraz : где ты тогда берешь popen? jfs 01.04.2016

pythonterminatepopensystermination

Ответы

Ответ 1 · рейтинг 1 · Brian Cain

Вы не можете ожидать, что обработчик сигнала, вызывающий исключение, будет распространяться через стек вызовов, он вызывается в другом контексте.

popen.terminate() будет генерировать SIGTERM в системах posix, поэтому у вас должен быть обработчик сигнала для SIGTERM, а не SIGALRM.

Вместо того, чтобы вызывать исключение в вашем обработчике сигналов, вы должны установить некоторую переменную, которую вы периодически проверяете, чтобы остановить активность.

В качестве альтернативы, если у вас нет обработчика сигнала для SIGTERM, обработчик по умолчанию, вероятно, сгенерирует исключение KeyboardInterrupt.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы