12
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

timeout付きinputを作った

Posted at

タイムアウト付きのinput

概要

タイム付きのinputが欲しくなったので自分で作ってPyPIに公開してみた。(1回公開したけどバグってたので削除済み)

ググって参考にしたもの

Python 3 Timed Input - Stack Overflow

困ったこと

PythonのselectはWindowsのファイルオブジェクトを受理できないのでWindowsとUnix系で実装を分ける必要があった。

判別方法

>>> import platform
>>> platform.system()
'Windows' or 'Darwin' or 'Linux' # など

Windows の場合

34.2. msvcrt — MS VC++実行時システムの有用なルーチン群 — Python 3.6.1 ドキュメント

ドキュメントの最初にgetpassモジュールに使われていると書いてあったので参考にした。
cpython/getpass.py at 3.6 · python/cpython

import msvcrt
import time


DEFAULT_TIMEOUT = 30.0

def win_input_with_timeout(prompt='', timeout=DEFAULT_TIMEOUT):
    begin = time.monotonic()
    end = begin + timeout
    for c in prompt:
        msvcrt.putwch(c)
    line = ''
    is_timeout = True
    while time.monotonic() < end:
        if msvcrt.kbhit():
            c = msvcrt.getwch()
            msvcrt.putwch(c)
            if c == '\r' or c == '\n':
                is_timeout = False
                break
            if c == '\003':
                raise KeyboardInterrupt
            if c == '\b':
                line = line[:-1]
            else:
                line = line + c
        time.sleep(0.05)
    msvcrt.putwch('\r')
    msvcrt.putwch('\n')
    if is_timeout:
        raise TimeoutOccurred
    return line

msvcrt.kbhit()の呼び出しが重たいみたいのでtime.sleep(0.05)を入れないとCPU使用率が上がるみたい。

Unix系の場合

signalとかthreadとかselectとか実現できそうな方法はいろいろあるけどselectで実装

import sys
import select


def unix_input_with_timeout(prompt='', timeout=DEFAULT_TIMEOUT):
    sys.stdout.write(prompt)
    sys.stdout.flush()
    (ready, _, _) = select.select([sys.stdin], [], [], timeout)
    if ready:
        return sys.stdin.readline().rstrip('\n')
    else:
        raise TimeoutOccurred

インストール

$ pip install inputimeout

使い方

from inputimeout import inputimeout, TimeoutOccurred
try:
    something = inputimeout(prompt='>>', timeout=5)
except TimeoutOccurred:
    print('Timeout!')
    something = 'something'

リポジトリ

johejo/inputimeout: Standard input with timeout.

12
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?