2016-06-10 4 views
1

Я пишу небольшую, единственную функцию, которая предназначена для запроса пользовательского ввода с задержкой по времени. Когда время задержки заканчивается, функция должна возвращать None вместо ответа пользователя, а затем продолжить с остальной частью скрипта.Как можно вернуть управление из функции обработчика сигнала, которая была определена внутри функции?

В текущей реализации пользовательский ввод работает и тайм-аут работает с сообщением таймаута, напечатанным функцией обработчика сигнала, которая определена внутри функции (я хочу, чтобы эта внешняя функция была достаточно автономной). Однако обработка затем останавливается (а не выходит из цикла while, определенного в функции main), и я не уверен, почему.

Как я могу обработать, чтобы продолжить? Я неправильно использую signal? Может ли использоваться лямбда вместо явно определенной функции для функции обработчика?

#!/usr/bin/env python 

from __future__ import print_function 
import signal 

import propyte 

def main(): 

    response = "yes" 
    while response is not None: 
     response = get_input_nonblocking(
      prompt = "ohai? ", 
      timeout = 5 
     ) 
    print("start non-response procedures") 
    # do things 

def get_input_nonblocking(
    prompt   = "", 
    timeout   = 5, 
    message_timeout = "prompt timeout" 
    ): 
    def timeout_manager(signum, frame): 
     print(message_timeout) 
    #signal.signal(signal.SIGALRM, lambda: print(message_timeout)) 
    signal.signal(signal.SIGALRM, timeout_manager) 
    signal.alarm(timeout) 
    try: 
     response = propyte.get_input(prompt) 
     return response 
    except: 
     return None 

if __name__ == '__main__': 
    main() 

ответ

2

У вас есть почти все, но вам нужно поднять исключение внутри вашего обработчика сигнала. raw_input будет блокироваться, пока что-то не произойдет, ни вход, ни исключение. Если вы возбудите исключение в обработчике сигнала, то это приведет к прерыванию raw_input, и выполнение будет попадать в except в вашу функцию get_input_non_blocking. Вот пример игрушки.

import signal 
def timeout(signum, frame): 
    raise IOError("bye!") 

signal.signal(signal.SIGALRM, timeout) 
def input(): 
    try: 
      print("omgplz: ") 
      return raw_input() 
    except IOError: 
      return None 

signal.alarm(5) 
txt = input() 
signal.alarm(0) 
print(txt) 

Там еще некоторое обсуждение и альтернативный подход с использованием select в этом ответе здесь: Keyboard input with timeout in Python

Надежда, что помогает!