raw_input [duplicate]に制限時間制限を設定する方法
-
05-10-2019 - |
質問
この質問にはすでに答えがあります:
- 関数呼び出しのタイムアウト 14の回答
Pythonでは、ユーザーの入力を待っている間に時間をカウントする方法があります。たとえば、30秒後に、 raw_input()
関数は自動的にスキップされますか?
解決
Signal.Alarm @Jerの推奨ソリューションに基づいている機能は、残念ながらUNIXのみです。クロスプラットフォームまたはWindows固有のソリューションが必要な場合は、それを基にすることができます Threading.timer 代わりに、使用します thread.interrupt_main 送信するには KeyboardInterrupt
タイマースレッドからメインスレッドへ。つまり:
import thread
import threading
def raw_input_with_timeout(prompt, timeout=30.0):
print prompt,
timer = threading.Timer(timeout, thread.interrupt_main)
astring = None
try:
timer.start()
astring = raw_input(prompt)
except KeyboardInterrupt:
pass
timer.cancel()
return astring
これは、30秒のタイムアウトであろうと、ユーザーがControl-Cをヒットして何かをあきらめることを明示的に決定するかどうかにかかわらず、これは何も返されませんが、同じ方法で2つのケースを扱うことは問題ないようです(区別する必要がある場合は、使用できます。タイマーの場合、メインスレッドを中断する前に、タイムアウトという事実をどこかに記録するあなた自身の関数 もっている 起こった、そしてあなたのハンドラーで KeyboardInterrupt
「どこか」にアクセスして、2つのケースのどれが発生したかを差別します)。
編集: :私はこれが機能していると誓うことができたかもしれませんが、私は間違っていたに違いありません - 上記のコードは明らかに必要なものを省略します timer.start()
, と それでも、私はそれをもう動作させることができません。 select.select
試してみるべき明らかな他のことですが、Windowsの「通常のファイル」(STDINを含む)では機能しません。UNIXでは、すべてのファイル、Windows、ソケットでのみ動作します。
したがって、クロスプラットフォーム「タイムアウトを使用した生の入力」を実行する方法がわかりません。 Windows固有のものは、タイトなループポーリングで構築できます msvcrt.kbhit, 、実行する msvcrt.getche
(そして、出力が完了したことを示すのがリターンであるかどうかを確認します。その場合、ループから抜け出し、そうでなければ蓄積して待ち続けます)。必要に応じてタイムアウトの時間を確認します。 Windowsマシンがないのでテストできません(すべてMacとLinuxのものです)が、ここでは テストされていないコード 私は提案します:
import msvcrt
import time
def raw_input_with_timeout(prompt, timeout=30.0):
print prompt,
finishat = time.time() + timeout
result = []
while True:
if msvcrt.kbhit():
result.append(msvcrt.getche())
if result[-1] == '\r': # or \n, whatever Win returns;-)
return ''.join(result)
time.sleep(0.1) # just to yield to other processes/threads
else:
if time.time() > finishat:
return None
コメントのOPは、彼がしたくないと言っています return None
タイムアウト時に、しかし代替手段は何ですか?例外を上げますか?別のデフォルト値を返しますか?彼が望んでいる代替手段が何であれ、私の代わりにそれをはっきりと置くことができます return None
;-).
ユーザーが入力しているからといってタイムアウトしたくない場合 ゆっくり (対照的に、まったく入力していません! - )、成功したキャラクター入力のたびにFinishatを再計算できます。
他のヒント
この問題の解決策を見つけました ブログ投稿で. 。これがそのブログ投稿のコードです:
import signal
class AlarmException(Exception):
pass
def alarmHandler(signum, frame):
raise AlarmException
def nonBlockingRawInput(prompt='', timeout=20):
signal.signal(signal.SIGALRM, alarmHandler)
signal.alarm(timeout)
try:
text = raw_input(prompt)
signal.alarm(0)
return text
except AlarmException:
print '\nPrompt timeout. Continuing...'
signal.signal(signal.SIGALRM, signal.SIG_IGN)
return ''
ご注意ください: このコードは、 *nix ossでのみ動作します.
from threading import Timer
def input_with_timeout(x):
def time_up():
answer= None
print 'time up...'
t = Timer(x,time_up) # x is amount of time in seconds
t.start()
try:
answer = input("enter answer : ")
except Exception:
print 'pass\n'
answer = None
if answer != True: # it means if variable have somthing
t.cancel() # time_up will not execute(so, no skip)
input_with_timeout(5) # try this for five seconds
それは自己定義であるので...コマンドラインプロンプトで実行してください、私はあなたがこれを読んで答えを得ることを願っています Python Doc このコードで起こったことが明確になります!!
入力()関数は、ユーザーが何かを入力するのを待つように設計されています(少なくとも[Enter]キー)。
入力()を使用するために死んでいない場合、以下はTKINTERを使用してはるかに軽いソリューションです。 TKINTERでは、ダイアログボックス(および任意のウィジェット)は、特定の時間後に破壊することができます。
これが例です:
import tkinter as tk
def W_Input (label='Input dialog box', timeout=5000):
w = tk.Tk()
w.title(label)
W_Input.data=''
wFrame = tk.Frame(w, background="light yellow", padx=20, pady=20)
wFrame.pack()
wEntryBox = tk.Entry(wFrame, background="white", width=100)
wEntryBox.focus_force()
wEntryBox.pack()
def fin():
W_Input.data = str(wEntryBox.get())
w.destroy()
wSubmitButton = tk.Button(w, text='OK', command=fin, default='active')
wSubmitButton.pack()
# --- optionnal extra code in order to have a stroke on "Return" equivalent to a mouse click on the OK button
def fin_R(event): fin()
w.bind("<Return>", fin_R)
# --- END extra code ---
w.after(timeout, w.destroy) # This is the KEY INSTRUCTION that destroys the dialog box after the given timeout in millisecondsd
w.mainloop()
W_Input() # can be called with 2 parameter, the window title (string), and the timeout duration in miliseconds
if W_Input.data : print('\nYou entered this : ', W_Input.data, end=2*'\n')
else : print('\nNothing was entered \n')
時限数学テストにかかる呪いの例
#!/usr/bin/env python3
import curses
import curses.ascii
import time
#stdscr = curses.initscr() - Using curses.wrapper instead
def main(stdscr):
hd = 100 #Timeout in tenths of a second
answer = ''
stdscr.addstr('5+3=') #Your prompt text
s = time.time() #Timing function to show that solution is working properly
while True:
#curses.echo(False)
curses.halfdelay(hd)
start = time.time()
c = stdscr.getch()
if c == curses.ascii.NL: #Enter Press
break
elif c == -1: #Return on timer complete
break
elif c == curses.ascii.DEL: #Backspace key for corrections. Could add additional hooks for cursor movement
answer = answer[:-1]
y, x = curses.getsyx()
stdscr.delch(y, x-1)
elif curses.ascii.isdigit(c): #Filter because I only wanted digits accepted
answer += chr(c)
stdscr.addstr(chr(c))
hd -= int((time.time() - start) * 10) #Sets the new time on getch based on the time already used
stdscr.addstr('\n')
stdscr.addstr('Elapsed Time: %i\n'%(time.time() - s))
stdscr.addstr('This is the answer: %s\n'%answer)
#stdscr.refresh() ##implied with the call to getch
stdscr.addstr('Press any key to exit...')
curses.wrapper(main)
Linuxの下では、呪いとGetch機能を使用して、その非ブロックを使用できます。 getch()を参照してください
https://docs.python.org/2/library/curses.html
キーボード入力をx秒間待機する関数(最初にcursesウィンドウ(win1)を初期化する必要があります!
import time
def tastaturabfrage():
inittime = int(time.time()) # time now
waitingtime = 2.00 # time to wait in seconds
while inittime+waitingtime>int(time.time()):
key = win1.getch() #check if keyboard entry or screen resize
if key == curses.KEY_RESIZE:
empty()
resize()
key=0
if key == 118:
p(4,'KEY V Pressed')
yourfunction();
if key == 107:
p(4,'KEY K Pressed')
yourfunction();
if key == 99:
p(4,'KEY c Pressed')
yourfunction();
if key == 120:
p(4,'KEY x Pressed')
yourfunction();
else:
yourfunction
key=0