2016-03-31 14 views
1

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

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: 
... 

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

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

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

... 
    signal.signal(signal.SIGTERM, handler) 
    signal.alarm(timeout_duration) 
    try: 
     result = func(*args, **kwargs) 
    except TimeoutError as exc: 
     result = default 
     popen.terminate() 
... 
+0

Что вы подразумеваете под * «программа, выполняемая этой функцией» *? Это внешний процесс, запущенный модулем 'subprocess'? Есть ли потоки потомков? Выходит ли процесс, если вы отправляете сигнал SIGTERM? Какова ваша версия Python? Этого должно быть достаточно, чтобы передать параметр 'timeout' в' process.wait() 'и вызывать' process.terminate() 'on TimeoutError, если нет потомков, и процесс выходит из' SIGTERM'. – jfs

+0

@ J.F.Sebastian этот код запускает функцию, которая запускает код fortran, который я хочу ограничить время работы, чтобы сэкономить процессор. Все это funtion оставляет код fortran в фоновом режиме и пропускает к другому элементу in for loop, который накапливается в процессоре после 100 циклов, и позволяет сказать, что я хочу завершить сеанс перед тем, как перейти к другому элементу. Python версии 2.7. – jackaraz

+0

Возможно, связано: [Выполнить команду за указанное время и затем прервать, если время превышает] (http://unix.stackexchange.com/q/23145) – GingerPlusPlus

ответ

1

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

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

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

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

+0

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

+0

1- исключения распространяются в основном потоке. Проблема может заключаться в том, что 'func()' может (из-за ошибки) забыть вызывать 'PyErr_CheckSignal()' на 'EINTR' в своем C-коде, и поэтому обработчик сигнала Python не вызывается до тех пор, пока' func() 'не вернет управление переводчику. 2- Что необходимо для отправки SIGTERM в процесс python. Кажется, что OP хочет закончить дочерний процесс. Цель «SIGALRM» - прервать любой процесс python, например, 'process.wait()'. 3, если код может периодически проверять переменную, если только код не находится в потоке; легче привлечь исключение – jfs