2015-02-02 2 views
2

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

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

import sys 
import time 
from select import select 

timeout = 4 
prompt = "Type any number from 0 up to 9" 
default = 99 

def input_with(prompt, timeout, default): 
    """Read an input from the user or timeout""" 
    print prompt, 
    sys.stdout.flush() 
    rlist, _, _ = select([sys.stdin], [], [], timeout) 
    if rlist: 
     s = int(sys.stdin.read().replace('\n','')) 
    else: 
     s = default 
     print s 
    return s 

я собираюсь запустить Raspberry Pi без полной клавиатуры, это означает, что я не буду иметь ключ возврата. Таким образом невозможно будет проверить ввод клавиатуры.

Мое сомнение в том, что можно получить ввод пользователя без нажатия клавиши ввода и сохранения таймаута для ввода.

Я видел много тем, говорящих обо всех проблемах (тайм-аут и ввод без нажатия возврата), но ничего не происходит вместе.

Заранее благодарим за любую помощь!

+0

Это интересный вопрос. 'stdin' не работает так, это строка за строкой. Вы должны смотреть на захват tty прямо так или иначе. Подумайте, как при вводе пароля при входе в систему, как он обходит stdin. – robert

+0

[Простота адаптации 'readchar' для принятия параметра timeout' (https://github.com/magmax/python-readchar/blob/e020e152f1787074ef915e50f46c407ca8ac355b/readchar/readchar_linux.py). Это взято из [ответа] (http://stackoverflow.com/a/25342814/4279) на [Python читает один символ от пользователя] (http://stackoverflow.com/q/510357/4279) – jfs

ответ

0

Я не думаю, что это просто так, как вы хотите, чтобы прочитать содержимое ожидания на линии, даже если ввод не был нажат (это правильно?).

Лучшее предложение, которое я могу предложить, состоит в том, что вы захватываете каждый символ, когда он нажимается, и вызывается после того, как прошло время. Вы можете захватить ввод на основе каждого символа, установив CBREAK режим: tty.setcbreak()

import sys 
from select import select 
import tty 
import termios 

try: 
    # more correct to use monotonic time where available ... 
    from time33 import clock_gettime 
    def time(): return clock_gettime(0) 
except ImportError: 
    # ... but plain old 'time' may be good enough if not. 
    from time import time 

timeout = 4 
prompt = "Type any number from 0 up to 9" 
default = 99 

def input_with(prompt, timeout, default): 
    """Read an input from the user or timeout""" 
    print prompt, 
    sys.stdout.flush() 

    # store terminal settings 
    old_settings = termios.tcgetattr(sys.stdin) 

    buff = '' 
    try:  
     tty.setcbreak(sys.stdin) # flush per-character 

     break_time = time() + timeout 

     while True: 

      rlist, _, _ = select([sys.stdin], [], [], break_time - time()) 
      if rlist: 
       c = sys.stdin.read(1) 

       # swallow CR (in case running on Windows) 
       if c == '\r': 
        continue 
       # newline EOL or EOF are also end of input 
       if c in ('\n', None, '\x04'): 
        break # newline is also end of input 
       buff += c 

       sys.stdout.write(c) # echo back 
       sys.stdout.flush() 

      else: # must have timed out 
       break 

    finally: 
     # put terminal back the way it was 
     termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings) 

    if buff: 
     return int(buff.replace('\n','').strip()) 
    else: 
     sys.stdout.write('%d' % default) 
     return default 
+0

'time.time()' можно установить обратно. Вот ['time.monotonic()' реализация для Python 2.7 на Ubuntu] (https://gist.github.com/zed/5073409) – jfs

+1

, вы должны, вероятно, также позволить символам 'eof' и' eol' прекращать ввод (в дополнение к 'b '\ n'') - см.' stty -a'. – jfs

+0

Спасибо, я не уверен, что вы имеете в виду о 'time.time'. Является ли подразумеваемым, что это ненадежно по этой причине? Я не верю, что EOL является проблемой для малины. На платформе non * nix вы можете ее поддерживать, но ее, вероятно, следует игнорировать. – robert

Смежные вопросы