Jak sprawić, aby python czekał na naciśnięty klawisz?


Odpowiedzi:


543

W Pythonie 3 użyj input():

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

W Pythonie 2 użyj raw_input():

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

To tylko czeka, aż użytkownik naciśnie klawisz Enter.

Można chcieć użyć msvcrt ((tylko Windows / DOS) Moduł msvcrt daje dostęp do szeregu funkcji w bibliotece Microsoft Visual C / C ++ Runtime Library (MSVCRT)):

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

To powinno poczekać na naciśnięcie klawisza.

Dodatkowe informacje:

w Pythonie 3 raw_input()nie istnieje

W Python 2 input(prompt)jest równoważne zeval(raw_input(prompt))


54
Otrzymuję ten błąd, gdy próbuję to zrobić w Pythonie 2.7: „Błąd składni: nieoczekiwany błąd EOF podczas analizowania”
— Jon Tirsen,

8
@ Solarsaturn9 i coraz większa ich liczba nie. Tak więc ta odpowiedź nie zadziałała dla mnie i dla wielu innych, którzy tu przychodzą.
— ctrl-alt-delor

5
@richard przy użyciu input () powinien również działać na innych platformach. To niedorzeczne, aby zadokować punkty, aby zapewnić alternatywne rozwiązanie tylko dla systemu Windows, gdy pierwsze rozwiązanie jest wieloplatformowe.
— Cory Buckley

7
@ Solarsaturn9 przeczytaj pytanie i odpowiedz ponownie: inputnie kontynuuje się po naciśnięciu dowolnego klawisza, tylko po naciśnięciu klawisza enter.
— ctrl-alt-delor

13
@JonTirsen to dlatego, że Python 2.7 ma funkcję o nazwie input, która ocenia wprowadzony ciąg. Aby to naprawić, użyj raw_input
— Samy Bencherif

316

Jednym ze sposobów na zrobienie tego w Pythonie 2 jest użycie raw_input():

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

W python3 jest po prostu input()


17
A kiedy może to być jeden z wielu kluczy? Nie tylko enter?
— noio

33
W Pythonie 3+ zmieniło się to na just input().
— palswim

Używając szóstki dla kodu kompatybilnego z Py2 i Py3:from six.moves import input; input("Press Enter to continue...")
— rcoup

56

W moim systemie Linux używam następującego kodu. Jest to podobne do kodu, który widziałem gdzie indziej (na przykład w starych pytaniach do Pythona), ale kod ten obraca się w ciasnej pętli, w której ten kod nie działa i jest wiele dziwnych przypadków narożnych, których kod nie uwzględnia tego kod robi.

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)

Chociaż jest to moja ulubiona z odpowiedzi tutaj, podobnie jak inni nie łapią takich rzeczy, jak zmiana, kontrola itp.
— Mala

1
@Mala, że ​​prawie nie jest możliwe w czystym Pythonie; może powinieneś napisać moduł C?
— kot

W moim systemie pojawia się „\ x03” podczas przerwania klawiatury (Ctrl-C).
— NRD

1
ctrl-c jest ascii 3, więc należy się tego spodziewać. Jeśli chcesz podnieść sygnał na ctrl-c, łatwym rozwiązaniem jest umieszczenie if ord (wartość_wrócona) == 3: os.kill (os.getpid (), signal.SIGINT), ale możesz również wyłączyć przetwarzanie sygnału przez attrs [0] | = termios.BRKINT, attrs [3]! = termios.ISIG, i pozbywaj się wyjątku przetwarzania KeyboardInterrupt. Uwaga - Zmieniłem wartość zwracaną dla KeyboardInterrupt na „\ x03” na cześć twojego zapytania (a ponieważ powoduje to, że ten kod zawsze zwraca ciąg znaków).
— mheyman

Jak można dostosować powyższy kod, aby zwracał krotkę dla złożonego naciśnięcia klawisza, takiego jak „Page Up” lub „Left Arrow”?
— Derek

33

Jeśli nie masz nic przeciwko w zależności od poleceń systemowych, możesz użyć następujących opcji:

Linux:

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

Windows:

import os
os.system("pause")

Jeśli chcesz kontynuować bieg, dopóki nie zostanie podniesiony sygnał (jak SIGINT), możesz również sprawdzić wartość zwrotną z, systema następnie zadzwonić sys.exit(0).
— James Taylor

29

Po prostu używa

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

spowoduje błąd SyntaxError: oczekiwany EOF podczas analizowania.

Proste zastosowanie poprawki:

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

5
Nie używaj inputw Pythonie 2 - poprawna funkcja to raw_input. W python 2 inputjest równoważne z eval(raw_input()).
— Blorgbeard wyszedł

2
Ignoruje to wszystkie klawisze, które użytkownik naciska, dopóki nie naciśnie Enter, co jest zupełnie inne niż to, o co prosi OP.
— Jonathan Hartley,

1
Ponadto, jeśli zamierzasz użyć polecenia „input”, wyłapanie błędu składni nie jest właściwe. Bez względu na to, jaki typ użytkownika zostanie oceniony, więc jeśli na przykład wpisze on „1/0”, wówczas podniesiony zostanie ZeroDivisionError zamiast SyntaxError, a program zakończy działanie.
— Jonathan Hartley

Jak wspomniano @Blorgbeard, wystarczy użyć raw_input („Naciśnij Enter, aby kontynuować ...”). Używam go teraz często podczas debugowania.
— alltrue

15

Pyton instrukcja przewiduje, co następuje:

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)

które można umieścić w walizce.


12
Dobrą praktyką jest skopiowanie rzeczy, do której się łączysz, aby wiedza pozostała, nawet jeśli link umrze (i tak się stanie!).
— Richard

1
Jak mogę to zrobić w Pythonie 3.x? W wersji 3.x, po zmianie instrukcji print na kompatybilną, po prostu zapętla się ona nieskończenie i nie czeka na dane wejściowe. Jednak działa świetnie w Pythonie 2.
— kot

Link został zaktualizowany w celu przekierowania na inną stronę. Nowy link jest tutaj.
— Matthias

15

Cross Platform, kod 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

Usunąłem fctl / nie blokujące rzeczy, ponieważ dawały IOErrors i nie potrzebowałem tego. Używam tego kodu, ponieważ chcę go zablokować. ;)

Uzupełnienie:

Zaimplementowałem to w pakiecie na PyPI z wieloma innymi dodatkami zwanymi konsolami :

>>> from console.utils import wait_key

>>> wait_key()
'h'

1
Wystąpił błąd: niewłaściwy ioctl dla urządzenia ”
— Benoit

@Benoit, który system operacyjny?
— Gringo Suave

14

Nie znam metody niezależnej od platformy, ale w systemie Windows, jeśli używasz modułu msvcrt, możesz użyć jego funkcji getch:

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

mscvcrt zawiera również nieblokującą funkcję kbhit (), aby sprawdzić, czy klawisz został naciśnięty bez czekania (nie jestem pewien, czy istnieje odpowiednia funkcja curses). W systemie UNIX istnieje pakiet curses, ale nie jestem pewien, czy można go użyć bez użycia go dla wszystkich danych wyjściowych ekranu. Ten kod działa w systemie UNIX:

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

Zauważ, że curses.getch () zwraca numer porządkowy wciśniętego klawisza, aby uzyskać taki sam wynik, jaki musiałem rzucić.


Używanie przekleństw jest o wiele ładniejsze niż dość skomplikowane przykłady opisane w instrukcji, nawet jeśli wiąże się to z ogromną zależnością. +1
— Damian

4

Jeśli chcesz poczekać na wejście (aby użytkownik pukający w klawiaturę nie spowodował, że wydarzy się coś nieoczekiwanego) użyj

sys.stdin.readline()

2
Chodzi o to, aby użytkownik nie musiał naciskać tylko klawisza Enter, aby na przykład móc po prostu uderzyć spacją. Jeśli potrzebujesz Enter, aby uniknąć czegoś niezamierzonego, to zły projekt.
— Synetech

3

Jestem nowy w Pythonie i już myślałem, że jestem zbyt głupi, aby odtworzyć najprostsze sugestie tutaj przedstawione. Okazuje się, że istnieje pułapka, o której należy wiedzieć:

Kiedy skrypt Pythona jest wykonywany z IDLE, niektóre polecenia IO wydają się zachowywać zupełnie inaczej (ponieważ tak naprawdę nie ma okna terminala).

Na przykład. msvcrt.getch nie blokuje i zawsze zwraca $ ff. Zostało to już zgłoszone dawno temu (patrz np. Https://bugs.python.org/issue9290 ) - i jest oznaczone jako naprawione, jakoś problem wydaje się utrzymywać w aktualnych wersjach python / IDLE.

Więc jeśli którykolwiek z powyższych kodów nie działa, spróbuj uruchomić skrypt ręcznie, a NIE z IDLE .


0

Jeśli chcesz sprawdzić, czy nacisnęli dokładnie klawisz (np. Powiedz „b”) Zrób to:

while True:
    choice = raw_input("> ")

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

8
Wymaga to od użytkownika wpisania „b” (lub czegoś innego), a następnie naciśnięcia enter, co jest zupełnie inne niż to, o co prosi OP.
— Jonathan Hartley

0

os.system wydaje się zawsze wywoływać sh, co nie rozpoznaje opcji s i n dla odczytu. Jednak polecenie odczytu można przekazać do bash:

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

2
Przeczytana dokumentacja każe mi myśleć, że nie upłynie limit czasu, chyba że podasz opcję -t.
— James King
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.