Rumah >pembangunan bahagian belakang >Tutorial Python >Bagaimanakah saya dapat mengesan input papan kekunci dalam skrip Python yang berjalan dari terminal?

Bagaimanakah saya dapat mengesan input papan kekunci dalam skrip Python yang berjalan dari terminal?

DDD
DDDasal
2024-10-29 12:37:021038semak imbas

How do I detect keyboard input in a Python script running from the terminal?

Bagaimanakah untuk mengesan input papan kekunci dalam skrip daripada terminal?

Tangkapan kunci Segerak/Menyekat:

Input mudah atau input_raw, penyekatan fungsi yang mengembalikan teks yang ditaip oleh pengguna sebaik sahaja mereka menekan baris baharu.

<code class="python">typedString = raw_input()</code>

Fungsi menyekat mudah yang menunggu pengguna menekan satu kekunci, kemudian mengembalikan kekunci itu

<code class="python">class _Getch:
 &quot;&quot;&quot;Gets a single character from standard input.  Does not echo to the
screen. From http://code.activestate.com/recipes/134892/&quot;&quot;&quot;
def __init__(self):
  try:
    self.impl = _GetchWindows()
  except ImportError:
    try:
      self.impl = _GetchMacCarbon()
    except(AttributeError, ImportError):
      self.impl = _GetchUnix()

def __call__(self): return self.impl()


class _GetchUnix:
def __init__(self):
  import tty, sys, termios # import termios now or else you'll get the Unix version on the Mac

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()

class _GetchMacCarbon:
&quot;&quot;&quot;
A function which returns the current ASCII key that is down;
if no ASCII key is down, the null string is returned.  The
page http://www.mactech.com/macintosh-c/chap02-1.html was
very helpful in figuring out how to do this.
&quot;&quot;&quot;
def __init__(self):
  import Carbon
  Carbon.Evt #see if it has this (in Unix, it doesn't)

def __call__(self):
  import Carbon
  if Carbon.Evt.EventAvail(0x0008)[0]==0: # 0x0008 is the keyDownMask
    return ''
  else:
    #
    # The event contains the following info:
    # (what,msg,when,where,mod)=Carbon.Evt.GetNextEvent(0x0008)[1]
    #
    # The message (msg) contains the ASCII char which is
    # extracted with the 0x000000FF charCodeMask; this
    # number is converted to an ASCII character with chr() and
    # returned
    #
    (what,msg,when,where,mod)=Carbon.Evt.GetNextEvent(0x0008)[1]
    return chr(msg &amp; 0x000000FF)


def getKey():
  inkey = _Getch()
  import sys
  for i in xrange(sys.maxint):
    k=inkey()
    if k<>'':break

  return k</code>

Tangkapan kekunci tak segerak:

Panggil balik yang dipanggil dengan kekunci yang ditekan apabila pengguna menaip kekunci ke dalam gesaan arahan, walaupun semasa menaip sesuatu ke dalam jurubahasa (pencatat kunci)

Panggil balik masih belum dilaksanakan.

Panggil balik yang dipanggil dengan teks yang ditaip selepas pengguna menekan enter (pembantu kunci masa nyata yang kurang)

Panggil balik belum lagi telah dilaksanakan.

Panggil balik yang dipanggil dengan kekunci ditekan apabila program sedang berjalan (katakan, dalam gelung for atau gelung while)

Windows:

<code class="python">import threading
from win32api import STD_INPUT_HANDLE
from win32console import GetStdHandle, KEY_EVENT, ENABLE_ECHO_INPUT, ENABLE_LINE_INPUT, ENABLE_PROCESSED_INPUT


class KeyAsyncReader():
  def __init__(self):
    self.stopLock = threading.Lock()
    self.stopped = True
    self.capturedChars = &quot;&quot;

    self.readHandle = GetStdHandle(STD_INPUT_HANDLE)
    self.readHandle.SetConsoleMode(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT)



  def startReading(self, readCallback):
    self.stopLock.acquire()

    try:
      if not self.stopped:
        raise Exception(&quot;Capture is already going&quot;)

      self.stopped = False
      self.readCallback = readCallback

      backgroundCaptureThread = threading.Thread(target=self.backgroundThreadReading)
      backgroundCaptureThread.daemon = True
      backgroundCaptureThread.start()
    except:
      self.stopLock.release()
      raise

    self.stopLock.release()


  def backgroundThreadReading(self):
    curEventLength = 0
    curKeysLength = 0
    while True:
      eventsPeek = self.readHandle.PeekConsoleInput(10000)

      self.stopLock.acquire()
      if self.stopped:
        self.stopLock.release()
        return
      self.stopLock.release()


      if len(eventsPeek) == 0:
        continue

      if not len(eventsPeek) == curEventLength:
        if self.getCharsFromEvents(eventsPeek[curEventLength:]):
          self.stopLock.acquire()
          self.stopped = True
          self.stopLock.release()
          break

        curEventLength = len(eventsPeek)



  def getCharsFromEvents(self, eventsPeek):
    callbackReturnedTrue = False
    for curEvent in eventsPeek:
      if curEvent.EventType == KEY_EVENT:
              if ord(curEvent.Char) == 0 or not curEvent.KeyDown:
                pass
              else:
                curChar = str(curEvent.Char)
                if self.readCallback(curChar) == True:
                  callbackReturnedTrue = True


    return callbackReturnedTrue

  def stopReading(self):
    self.stopLock.acquire()
    self.stopped = True
    self.stopLock.release()</code>

Polling:

Pengguna hanya mahu dapat melakukan sesuatu apabila kekunci ditekan, tanpa perlu menunggu kekunci itu (jadi ini sepatutnya tidak menyekat) . Oleh itu mereka memanggil fungsi poll() dan sama ada mengembalikan kunci, atau mengembalikan Tiada. Ini boleh menjadi lossy (jika mereka mengambil masa terlalu lama untuk antara tinjauan pendapat mereka boleh terlepas kunci) atau tidak rugi (peninjau akan menyimpan sejarah semua kekunci yang ditekan, jadi apabila fungsi poll() memintanya, mereka akan sentiasa dikembalikan dalam urutan ditekan).

Windows dan OS X (dan mungkin Linux):

<code class="python">global isWindows

isWindows = False
try:
  from win32api import STD_INPUT_HANDLE
  from win32console import GetStdHandle, KEY_EVENT, ENABLE_ECHO_INPUT, ENABLE_LINE_INPUT, ENABLE_PROCESSED_INPUT
  isWindows = True
except ImportError as e:
  import sys
  import select
  import termios


class KeyPoller():
  def __enter__(self):
    global isWindows
    if isWindows:
      self.readHandle = GetStdHandle(STD_INPUT_HANDLE)
      self.readHandle.SetConsoleMode(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT)
      
      self.curEventLength = 0
      self.curKeysLength = 0
      
      self.capturedChars = []
    else:
      # Save the terminal settings
      self.fd = sys.stdin.fileno()
      self.new_term = termios.tcgetattr(self.fd)
      self.old_term = termios.tcgetattr(self.fd)
      
      # New terminal setting unbuffered
      self.new_term[3] = (self.new_term[3] &amp; ~termios.ICANON &amp; ~termios.ECHO)
      termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.new_term)
      
    return self
  
  def __exit__(self, type, value, traceback):
    if isWindows:
      pass
    else:
      termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.old_term)
  
  def poll(self):
    if isWindows:
      if not len(self.capturedChars) == 0:
        return self.capturedChars.pop(0)

      eventsPeek = self.readHandle.PeekConsoleInput(10000)
</code>

Atas ialah kandungan terperinci Bagaimanakah saya dapat mengesan input papan kekunci dalam skrip Python yang berjalan dari terminal?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn