Pythonがキーが押されるのを待機させるにはどうすればよいですか?


571

ユーザーが任意のキーを押すまでスクリプトを待機させたい。

それ、どうやったら出来るの?

回答:


543

ではPythonの3の使用input()

input("Press Enter to continue...")

ではPythonの2の使用raw_input()

raw_input("Press Enter to continue...")

これは、ユーザーがEnterキーを押すのを待つだけです。

msvcrtを使用したい場合があります((Windows / DOSのみ)msvcrtモジュールを使用すると、Microsoft Visual C / C ++ランタイムライブラリ(MSVCRT)の多数の関数にアクセスできます。

import msvcrt as m
def wait():
    m.getch()

これはキーが押されるのを待つ必要があります。

追加情報:

Python 3にraw_input()は存在しません

Python 2ではinput(prompt)eval(raw_input(prompt))


54
Python 2.7でこれを実行しようとすると、このエラーが発生します。「SyntaxError:解析中に予期しないEOF」
Jon Tirsen

8
@ Solarsaturn9と増加し、多数はしません。したがって、この答えは私にとってはうまくいきませんでした。
ctrl-alt-delor 2015年

5
input()を使用した@richardは他のプラットフォームでも動作するはずです。最初のソリューションがマルチプラットフォームである場合、別のWindowsのみのソリューションを提供するためにポイントをドッキングするのはばかげています。
Cory Buckley

7
@ Solarsaturn9は質問を読んでもう一度回答しinputます。キーが押されても続行せず、Enterキーが押された場合のみ。
ctrl-alt-delor 2015年

13
@JonTirsenは、Python 2.7に、入力した文字列を評価するinputという関数があるためです。修正するには、raw_inputを使用します
Samy Bencherif

316

Python 2でこれを行う1つの方法は、以下を使用することraw_input()です。

raw_input("Press Enter to continue...")

python3ではそれだけです input()


17
いくつかのキーの1つになる可能性がある場合はどうでしょうか?だけじゃないenter
noio

33
Python 3+では、これはに変更されましたinput()
パルスイム

Py2およびPy3互換コードに6を使用:from six.moves import input; input("Press Enter to continue...")
rcoup

56

私のLinuxボックスでは、次のコードを使用します。これは、他の場所で見たコード(たとえば、古いpythonのFAQなど)に似ていますが、このコードは、このコードが実行しないタイトなループでスピンし、コードがこれを説明しない奇妙なコーナーケースがたくさんあります。コードはありません。

def read_single_keypress():
    """Waits for a single keypress on stdin.

    This is a silly function to call if you need to do it a lot because it has
    to store stdin's current setup, setup stdin for reading single keystrokes
    then read the single keystroke then revert stdin back after reading the
    keystroke.

    Returns a tuple of characters of the key that was pressed - on Linux, 
    pressing keys like up arrow results in a sequence of characters. Returns 
    ('\x03',) on KeyboardInterrupt which can happen when a signal gets
    handled.

    """
    import termios, fcntl, sys, os
    fd = sys.stdin.fileno()
    # save old state
    flags_save = fcntl.fcntl(fd, fcntl.F_GETFL)
    attrs_save = termios.tcgetattr(fd)
    # make raw - the way to do this comes from the termios(3) man page.
    attrs = list(attrs_save) # copy the stored version to update
    # iflag
    attrs[0] &= ~(termios.IGNBRK | termios.BRKINT | termios.PARMRK
                  | termios.ISTRIP | termios.INLCR | termios. IGNCR
                  | termios.ICRNL | termios.IXON )
    # oflag
    attrs[1] &= ~termios.OPOST
    # cflag
    attrs[2] &= ~(termios.CSIZE | termios. PARENB)
    attrs[2] |= termios.CS8
    # lflag
    attrs[3] &= ~(termios.ECHONL | termios.ECHO | termios.ICANON
                  | termios.ISIG | termios.IEXTEN)
    termios.tcsetattr(fd, termios.TCSANOW, attrs)
    # turn off non-blocking
    fcntl.fcntl(fd, fcntl.F_SETFL, flags_save & ~os.O_NONBLOCK)
    # read a single keystroke
    ret = []
    try:
        ret.append(sys.stdin.read(1)) # returns a single character
        fcntl.fcntl(fd, fcntl.F_SETFL, flags_save | os.O_NONBLOCK)
        c = sys.stdin.read(1) # returns a single character
        while len(c) > 0:
            ret.append(c)
            c = sys.stdin.read(1)
    except KeyboardInterrupt:
        ret.append('\x03')
    finally:
        # restore old state
        termios.tcsetattr(fd, termios.TCSAFLUSH, attrs_save)
        fcntl.fcntl(fd, fcntl.F_SETFL, flags_save)
    return tuple(ret)

これは私のお気に入りの回答ですが、他の人はシフト、コントロールなどのようなものをキャッチしません
Mala

1
@Malaは、純粋なPythonではほとんど不可能です。多分あなたはCモジュールを書くべきですか?
猫、

システムのキーボード割り込み(Ctrl-C)で「\ x03」が表示されます。
GDR

1
ctrl-cはASCII 3であるため、予想どおりです。ctrl-cでシグナルを発生させたい場合、簡単な解決策はif ord(returned_value)== 3:os.kill(os.getpid()、signal.SIGINT)を置くことですが、シグナル処理をオフにすることもできますattrs [0] | = termios.BRKINT、attrs [3]!= termios.ISIGにより、KeyboardInterrupt以外の処理を取り除きます。注-クエリを考慮して、KeyboardInterruptの戻り値を '\ x03'に変更しました(これにより、このコードは常に文字列を返します)。
mheyman 2018

上記のコードを調整して、「Page Up」や「左矢印」などの複雑なキーを押したときにタプルが返されるようにするにはどうすればよいでしょうか。
デレク

33

システムコマンドに応じて問題がなければ、以下を使用できます。

Linux:

import os
os.system('read -sn 1 -p "Press any key to continue..."')
print

ウィンドウズ:

import os
os.system("pause")

シグナルが発生するまで実行を継続する場合は(SIGINTなど)、からの戻り値を確認してsystemを呼び出すこともできますsys.exit(0)
James Taylor、

29

単に使用する

input("Press Enter to continue...")

SyntaxErrorが発生します。解析中にEOFが予期されます。

簡単な修正の使用:

try:
    input("Press enter to continue")
except SyntaxError:
    pass

5
inputPython 2 では使用しないでくださいraw_input。正しい関数はです。Python 2では、inputと同等eval(raw_input())です。
Blorgbeardは2014

2
これは、ユーザーがEnterキーを押すまで、ユーザーが押すすべてのキーを無視します。これは、OPが要求するものとはかなり異なります。
Jonathan Hartley

1
また、「input」を使用する場合、SyntaxErrorをキャッチすることは適切ではありません。ユーザーが入力したものは何でも評価されるため、たとえば「1/0」と入力すると、SyntaxErrorの代わりにZeroDivisionErrorが発生し、プログラムが終了します。
Jonathan Hartley

@Blorgbeardが述べたように、raw_input( "Enterを押して続行...")を使用するだけで十分です。今はデバッグ時によく使います。
2015

15

python マニュアルは以下を提供します:

import termios, fcntl, sys, os
fd = sys.stdin.fileno()

oldterm = termios.tcgetattr(fd)
newattr = termios.tcgetattr(fd)
newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
termios.tcsetattr(fd, termios.TCSANOW, newattr)

oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)

try:
    while 1:
        try:
            c = sys.stdin.read(1)
            print "Got character", repr(c)
        except IOError: pass
finally:
    termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
    fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)

これは、ユースケースに組み込むことができます。


12
リンクしているものをコピーして、リンクが切れたとしても(知識が失われても)知識が残るようにすることをお勧めします。
リチャード

1
Python 3.xでこれを機能させるにはどうすればよいですか?3.xでは、printステートメントを互換性のあるものに変更した後、これは無限にループし、入力を待機しません。Python 2でもうまく機能します。

リンクが更新され、別のページにリダイレクトされます。新しいリンクはこちらです。
Matthias

15

クロスプラットフォーム、Python 2/3コード:

# import sys, os

def wait_key():
    ''' Wait for a key press on the console and return it. '''
    result = None
    if os.name == 'nt':
        import msvcrt
        result = msvcrt.getch()
    else:
        import termios
        fd = sys.stdin.fileno()

        oldterm = termios.tcgetattr(fd)
        newattr = termios.tcgetattr(fd)
        newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
        termios.tcsetattr(fd, termios.TCSANOW, newattr)

        try:
            result = sys.stdin.read(1)
        except IOError:
            pass
        finally:
            termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)

    return result

fctl / non-blockingを削除しました。これはIOErrorsを与えていて、それを必要としなかったためです。ブロックしたいので、このコードを使用しています。;)

補遺:

私はこれをPyPIのパッケージに実装し、コンソールと呼ばれる他の多くの便利な機能を備えました:

>>> from console.utils import wait_key

>>> wait_key()
'h'

1
エラーが発生しました:デバイスのioctlが不適切です '
Benoit

@BenoitどのOSですか?
Gringo Suave

Linux-Ubuntu 20.04
ブノワ

14

プラットフォームに依存しない方法はわかりませんが、Windowsでは、msvcrtモジュールを使用すると、そのgetch関数を使用できます。

import msvcrt
c = msvcrt.getch()
print 'you entered', c

mscvcrtには、待機せずにキーが押されたかどうかを確認するための非ブロッキングkbhit()関数も含まれています(対応するcurses関数があるかどうか不明)。UNIXにはcursesパッケージがありますが、すべての画面出力に使用せずに使用できるかどうかはわかりません。このコードはUNIXで機能します。

import curses
stdscr = curses.initscr()
c = stdscr.getch()
print 'you entered', chr(c)
curses.endwin()

curses.getch()は押されたキーの序数を返すため、キャストする必要があるのと同じ出力が得られることに注意してください。


cursesの使用は、たとえそれが巨大な依存関係を伴うとしても、マニュアルで説明されているかなり複雑な例よりもはるかに優れています。+1
ダミアン

4

入力を待つ場合(ユーザーがキーボードをノックしても意図しないことが発生しないようにする場合)

sys.stdin.readline()

2
重要なのは、ユーザーがEnterキーだけを押す必要がないことです。たとえば、スペースバーをたたくだけです。意図しないことが起こらないようにするためにEnterキーが必要な場合、それは悪い設計です。
Synetech、

3

私はPythonが初めてで、ここで行った最も簡単な提案を再現するには愚かすぎるとすでに思っていました。結局のところ、知っておくべき落とし穴があります。

IDLEからpython-scriptを実行すると、一部のIOコマンドの動作が完全に異なるように見えます(実際にはターミナルウィンドウがないため)。

例えば。msvcrt.getchは非ブロッキングで、常に$ ffを返します。これはすでにかなり前に報告されています(例:https : //bugs.python.org/issue9290を参照))-修正済みとマークされているため、現在のバージョンのpython / IDLEでも問題が解決しないようです。

したがって、上記のコードのいずれかが機能しない場合は、IDLEからではなく、手動でスクリプトを実行してみてください。


0

彼らが正確なキーを押したかどうかを確認したい場合( 'b'のように)次のようにします:

while True:
    choice = raw_input("> ")

    if choice == 'b' :
        print "You win"
        input("yay")
        break

8
これには、ユーザーが「b」(または何か)を入力してEnterキーを押す必要があります。これは、OPが要求するものとはかなり異なります。
Jonathan Hartley、

0

os.systemは常にshを呼び出すようですが、これは読み取り用のsおよびnオプションを認識しません。ただし、読み取りコマンドはbashに渡すことができます。

 os.system("""bash -c 'read -s -n 1 -p "Press any key to continue..."'""")

2
ドキュメントを読んだので、-tオプションを指定しない限りタイムアウトしないと思います。
ジェームズキング
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.