사용자 입력에서 하나의 단일 문자를 읽는 방법이 있습니까? 예를 들어 터미널에서 하나의 키를 누르면 반환됩니다 (정렬 한 정렬 getch()
). Windows에 기능이 있다는 것을 알고 있지만 플랫폼 간 무언가를 원합니다.
답변
다음은 Windows, Linux 및 OSX에서 단일 문자를 읽는 방법을 알려주는 사이트 링크입니다. http://code.activestate.com/recipes/134892/
class _Getch:
"""Gets a single character from standard input. Does not echo to the
screen."""
def __init__(self):
try:
self.impl = _GetchWindows()
except ImportError:
self.impl = _GetchUnix()
def __call__(self): return self.impl()
class _GetchUnix:
def __init__(self):
import tty, sys
def __call__(self):
import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
class _GetchWindows:
def __init__(self):
import msvcrt
def __call__(self):
import msvcrt
return msvcrt.getch()
getch = _Getch()
답변
sys.stdin.read(1)
기본적으로 STDIN에서 1 바이트를 읽습니다.
기다리지 않는 방법을 사용해야하는 경우 \n
이전 답변에서 제안한대로이 코드를 사용할 수 있습니다.
class _Getch:
"""Gets a single character from standard input. Does not echo to the screen."""
def __init__(self):
try:
self.impl = _GetchWindows()
except ImportError:
self.impl = _GetchUnix()
def __call__(self): return self.impl()
class _GetchUnix:
def __init__(self):
import tty, sys
def __call__(self):
import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
class _GetchWindows:
def __init__(self):
import msvcrt
def __call__(self):
import msvcrt
return msvcrt.getch()
getch = _Getch()
( http://code.activestate.com/recipes/134892/ 에서 가져옴 )
답변
두 가지 답변으로 구두 인용 된 ActiveState 레시피 가 과도하게 엔지니어링되었습니다. 다음과 같이 정리할 수 있습니다.
def _find_getch():
try:
import termios
except ImportError:
# Non-POSIX. Return msvcrt's (Windows') getch.
import msvcrt
return msvcrt.getch
# POSIX system. Create and return a getch that manipulates the tty.
import sys, tty
def _getch():
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
return _getch
getch = _find_getch()
답변
readchar 라이브러리도 시도해 볼 가치가 있습니다.이 라이브러리는 부분적으로 다른 답변에서 언급 한 ActiveState 레시피를 기반으로합니다.
설치:
pip install readchar
용법:
import readchar
print("Reading a char:")
print(repr(readchar.readchar()))
print("Reading a key:")
print(repr(readchar.readkey()))
Python 2.7을 사용하여 Windows 및 Linux에서 테스트되었습니다.
Windows에서 문자 또는 ASCII 제어 코드에 매핑에만 키가 지원됩니다 ( Backspace, Enter, Esc, Tab, Ctrl+ 문자 ). GNU / 리눅스 (아마, 정확한 터미널에 따라?) 당신은 또한 얻을 Insert, Delete, Pg Up, Pg Dn, Home, End및 키 …하지만 다음에,에서 이러한 특수 키를 분리 문제가있다 .F nEsc
주의 사항 : 대부분의 (모두?) 답변과 마찬가지로 Ctrl+ C, Ctrl+ D및 Ctrl+ 와 같은 신호 키 Z는 잡히고 반환됩니다 ( 각각 '\x03'
, '\x04'
및 '\x1a'
). 프로그램이 중단되기 어려울 수 있습니다.
답변
다른 방법 :
import os
import sys
import termios
import fcntl
def getch():
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)
break
except IOError: pass
finally:
termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)
return c
에서 이 블로그 게시물 .
답변
here에 기반한이 코드 는 Ctrl+ C또는 Ctrl+ D를 누르면 KeyboardInterrupt 및 EOFError를 올바르게 발생 시킵니다.
Windows 및 Linux에서 작동해야합니다. 원본 소스에서 OS X 버전을 사용할 수 있습니다.
class _Getch:
"""Gets a single character from standard input. Does not echo to the screen."""
def __init__(self):
try:
self.impl = _GetchWindows()
except ImportError:
self.impl = _GetchUnix()
def __call__(self):
char = self.impl()
if char == '\x03':
raise KeyboardInterrupt
elif char == '\x04':
raise EOFError
return char
class _GetchUnix:
def __init__(self):
import tty
import sys
def __call__(self):
import sys
import tty
import termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
class _GetchWindows:
def __init__(self):
import msvcrt
def __call__(self):
import msvcrt
return msvcrt.getch()
getch = _Getch()
답변
(현재) 최상위 답변 (ActiveState 코드 포함)은 지나치게 복잡합니다. 단순한 함수로 충분할 때 클래스를 사용해야 할 이유가 없습니다. 아래는 동일하지만 더 읽기 쉬운 코드로 달성하는 두 가지 구현입니다.
이 두 가지 구현 모두 :
- Python 2 또는 Python 3에서 잘 작동합니다.
- Windows, OSX 및 Linux에서 작업
- 1 바이트 만 읽습니다 (즉, 개행을 기다리지 않습니다)
- 외부 라이브러리에 의존하지 않습니다
- 자체 포함 (함수 정의 외부의 코드 없음)
버전 1 : 읽기 쉽고 간단
def getChar():
try:
# for Windows-based systems
import msvcrt # If successful, we are on Windows
return msvcrt.getch()
except ImportError:
# for POSIX-based systems (with termios & tty support)
import tty, sys, termios # raises ImportError if unsupported
fd = sys.stdin.fileno()
oldSettings = termios.tcgetattr(fd)
try:
tty.setcbreak(fd)
answer = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, oldSettings)
return answer
버전 2 : 반복되는 가져 오기 및 예외 처리를 피하십시오.
[편집] ActiveState 코드의 장점 중 하나를 놓쳤습니다. 문자를 여러 번 읽으려는 경우 해당 코드는 Unix와 유사한 시스템에서 Windows 가져 오기 및 ImportError 예외 처리를 반복하는 데 드는 비용을 무시할 수 있습니다. 무시할 수있는 최적화보다 코드 가독성에 더 관심이 있어야하지만 ActiveState 코드와 동일하게 작동하고 더 읽기 쉬운 대안이 있습니다 (Louis의 대답과 비슷하지만 getChar ()는 독립적입니다).
def getChar():
# figure out which function to use once, and store it in _func
if "_func" not in getChar.__dict__:
try:
# for Windows-based systems
import msvcrt # If successful, we are on Windows
getChar._func=msvcrt.getch
except ImportError:
# for POSIX-based systems (with termios & tty support)
import tty, sys, termios # raises ImportError if unsupported
def _ttyRead():
fd = sys.stdin.fileno()
oldSettings = termios.tcgetattr(fd)
try:
tty.setcbreak(fd)
answer = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, oldSettings)
return answer
getChar._func=_ttyRead
return getChar._func()
위의 getChar () 버전 중 하나를 실행하는 예제 코드 :
from __future__ import print_function # put at top of file if using Python 2
# Example of a prompt for one character of input
promptStr = "Please give me a character:"
responseStr = "Thank you for giving me a '{}'."
print(promptStr, end="\n> ")
answer = getChar()
print("\n")
print(responseStr.format(answer))