функция ввода прерывания в определенное время python [duplicate]

С CLI в одной строке:

mysql --user=root --password=pass --host=localhost db_name --execute='select version()';

или

mysql -uroot -ppass -hlocalhost db_name -e 'select version()';

возвращает что-то вроде этого:

+-----------+
| version() |
+-----------+
| 5.6.34    |
+-----------+
32
задан pupeno 26 August 2009 в 16:19
поделиться

9 ответов

Пример, с которым вы связаны, неверен, и исключение на самом деле происходит при вызове обработчика аварий, а не при чтении блоков. Лучше попробуйте это:

import signal
TIMEOUT = 5 # number of seconds your want for timeout

def interrupted(signum, frame):
    "called when read times out"
    print 'interrupted!'
signal.signal(signal.SIGALRM, interrupted)

def input():
    try:
            print 'You have 5 seconds to type in your stuff...'
            foo = raw_input()
            return foo
    except:
            # timeout
            return

# set alarm
signal.alarm(TIMEOUT)
s = input()
# disable the alarm after success
signal.alarm(0)
print 'You typed', s
24
ответ дан user137673 21 August 2018 в 19:44
поделиться
  • 1
    Хорошее решение, это работает только на Linux. – Nadia Alramli 26 August 2009 в 20:25
  • 2
    Я изо всех сил пытаюсь получить ввод с тайм-аутом сегодня. Я просто хотел остановить воспроизведение изображений с жесткого диска, чтобы я мог остановить его, просто нажав клавишу, поэтому мне нужен небольшой тайм-аут (33 мс). Я просто хочу указать, что некоторые решения, которые вы найдете в stackoverflow, не работают на IDLE !! (Я не знаю почему). Вы должны выполнить их на терминале. А также самый полезный код, который я нашел в Интернете, это: home.wlu.edu/~levys/software/kbhit.py . Удачи! – jespestana 13 June 2013 в 00:47
  • 3
    Я пытался это решение, и это не работало в python3. Вы должны поднять ошибку в прерванной функции, чтобы поймать это исключение в определенной функции ввода - это заставит ее работать в python3. :) – rnbguy 4 June 2014 в 19:41
  • 4
    Ошибка отступов в строке 7. – anonymous 21 July 2017 в 23:22
  • 5
    Это не работает для меня. Он просто печатает "interrupted" через 5 секунд, но фактически не останавливает input. Он все еще ждет нажатия Enter, и он даже печатает любой текст, который я вводил после «Прерванный». появится сообщение. Протестировано на Linux с Python 2 и 3. – tobias_k 1 February 2018 в 13:01

Я провел около двадцати минут или около того, поэтому я подумал, что это стоит того, чтобы поместить это здесь. Тем не менее, это напрямую связано с ответом пользователя137673. Мне было очень полезно сделать что-то вроде этого:

#! /usr/bin/env python

import signal

timeout = None

def main():
    inp = stdinWait("You have 5 seconds to type text and press <Enter>... ", "[no text]", 5, "Aw man! You ran out of time!!")
    if not timeout:
        print "You entered", inp
    else:
        print "You didn't enter anything because I'm on a tight schedule!"

def stdinWait(text, default, time, timeoutDisplay = None, **kwargs):
    signal.signal(signal.SIGALRM, interrupt)
    signal.alarm(time) # sets timeout
    global timeout
    try:
        inp = raw_input(text)
        signal.alarm(0)
        timeout = False
    except (KeyboardInterrupt):
        printInterrupt = kwargs.get("printInterrupt", True)
        if printInterrupt:
            print "Keyboard interrupt"
        timeout = True # Do this so you don't mistakenly get input when there is none
        inp = default
    except:
        timeout = True
        if not timeoutDisplay is None:
            print timeoutDisplay
        signal.alarm(0)
        inp = default
    return inp

def interrupt(signum, frame):
    raise Exception("")

if __name__ == "__main__":
    main()
2
ответ дан dylnmc 21 August 2018 в 19:44
поделиться
  • 1
    Отличное решение. Очень хорошо работает в Python3. Невозможно проголосовать достаточно. – Regis May 25 April 2018 в 14:46

Не решение Python, но ...

Я столкнулся с этой проблемой со сценарием, работающим под CentOS (Linux), и то, что работало в моей ситуации, было просто запуском «read -t» Bash "в подпроцессе. Жестокий отвратительный хак, я знаю, но я чувствую себя достаточно виноватым в том, насколько хорошо он работал, и я хотел поделиться им со всеми здесь.

import subprocess
subprocess.call('read -t 30', shell=True)

Все, что мне нужно, было то, что ожидало 30 секунд, если только ENTER нажата клавиша. Это отлично работает.

7
ответ дан Locane 21 August 2018 в 19:44
поделиться

Следующий код работал для меня.

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

def _input(msg, q):
    ra = raw_input(msg)
    if ra:
        q.put(ra)
    else:
        q.put("None")
    return

def _slp(tm, q):
    time.sleep(tm)
    q.put("Timeout")
    return

def wait_for_input(msg="Press Enter to continue", time=10):
    q = Queue.Queue()
    th = threading.Thread(target=_input, args=(msg, q,))
    tt = threading.Thread(target=_slp, args=(time, q,))

    th.start()
    tt.start()
    ret = None
    while True:
        ret = q.get()
        if ret:
            th._Thread__stop()
            tt._Thread__stop()
            return ret
    return ret

print time.ctime()    
t= wait_for_input()
print "\nResponse :",t 
print time.ctime()
3
ответ дан Mechatron 21 August 2018 в 19:44
поделиться

Ответ Павла не совсем сработал. Модифицированный код ниже, который работает для меня на

  • windows 7 x64
  • ванильной CMD-оболочке (например, не git-bash или другой не-M $ shell) - ничего msvcrt работает в git-bash.
  • python 3.6

(Я отправляю новый ответ, потому что редактирование ответа Павла напрямую изменит его из python 2 .x -> 3.x, что кажется слишком большим для редактирования (py2 все еще используется)

import sys, time, msvcrt

def readInput( caption, default, timeout = 5):

    start_time = time.time()
    sys.stdout.write('%s(%s):'%(caption, default))
    sys.stdout.flush()
    input = ''
    while True:
        if msvcrt.kbhit():
            byte_arr = msvcrt.getche()
            if ord(byte_arr) == 13: # enter_key
                break
            elif ord(byte_arr) >= 32: #space_char
                input += "".join(map(chr,byte_arr))
        if len(input) == 0 and (time.time() - start_time) > timeout:
            print("timing out, using default value.")
            break

    print('')  # needed to move to next line
    if len(input) > 0:
        return input
    else:
        return default

# and some examples of usage
ans = readInput('Please type a name', 'john') 
print( 'The name is %s' % ans)
ans = readInput('Please enter a number', 10 ) 
print( 'The number is %s' % ans) 
3
ответ дан mike 21 August 2018 в 19:44
поделиться

И вот что работает в Windows

Мне не удалось заставить любой из этих примеров работать в Windows, поэтому я объединил несколько разных ответов StackOverflow, чтобы получить следующее:


import threading, msvcrt
import sys

def readInput(caption, default, timeout = 5):
    class KeyboardThread(threading.Thread):
        def run(self):
            self.timedout = False
            self.input = ''
            while True:
                if msvcrt.kbhit():
                    chr = msvcrt.getche()
                    if ord(chr) == 13:
                        break
                    elif ord(chr) >= 32:
                        self.input += chr
                if len(self.input) == 0 and self.timedout:
                    break    


    sys.stdout.write('%s(%s):'%(caption, default));
    result = default
    it = KeyboardThread()
    it.start()
    it.join(timeout)
    it.timedout = True
    if len(it.input) > 0:
        # wait for rest of input
        it.join()
        result = it.input
    print ''  # needed to move to next line
    return result

# and some examples of usage
ans = readInput('Please type a name', 'john') 
print 'The name is %s' % ans
ans = readInput('Please enter a number', 10 ) 
print 'The number is %s' % ans 
5
ответ дан Paul 21 August 2018 в 19:44
поделиться

Аналогично Locane для окон:

import subprocess  
subprocess.call('timeout /T 30')
1
ответ дан Petter Friberg 21 August 2018 в 19:44
поделиться
  • 1
    Если это имеет значение, тайм-аут был введен с Windows Vista или после нее. – DevPlayer 15 September 2016 в 12:43

Использование выбранного вызова короче и должно быть гораздо более портативным

import sys, select

print "You have ten seconds to answer!"

i, o, e = select.select( [sys.stdin], [], [], 10 )

if (i):
  print "You said", sys.stdin.readline().strip()
else:
  print "You said nothing!"
71
ответ дан Pontus 21 August 2018 в 19:44
поделиться
  • 1
    +1 для кросс-платформенного решения. – Great Turtle 4 June 2010 в 16:06
  • 2
    Я просто тестировал, и это НЕ работает для окон. Выбор доступен, но в окнах вход для выбора может быть только сокет - sys.stdin и дескрипторы файлов являются unix. В следующий раз я обязательно проверю. – Great Turtle 4 June 2010 в 16:19
  • 3
    Штопать. Ну, что же сам уважающий программист использует окна? ;) Для простого пользовательского ввода я предполагаю, что это можно сделать с помощью цикла вокруг «kbhit», который обнаруживает нажатия клавиш и «getch». с "time.sleep" перерыв после таймаута. Но это будет уродливо. – Pontus 10 June 2010 в 17:26

Поздний ответ:)

Я бы сделал что-то вроде этого:

from time import sleep

print('Please provide input in 20 seconds! (Hit Ctrl-C to start)')
try:
    for i in range(0,20):
        sleep(1) # could use a backward counter to be preeety :)
    print('No input is given.')
except KeyboardInterrupt:
    raw_input('Input x:')
    print('You, you! You know something.')

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

Надеюсь, это по крайней мере частично помогает. (Если кто-нибудь все это прочитает :))

-3
ответ дан try 21 August 2018 в 19:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: