"إذا أراد العامل أن يؤدي عمله بشكل جيد، فعليه أولاً أن يشحذ أدواته." - كونفوشيوس، "مختارات كونفوشيوس. لو لينجونج"
الصفحة الأمامية > برمجة > كيف يمكنني اكتشاف إدخال لوحة المفاتيح في برنامج Python النصي الذي يتم تشغيله من الجهاز؟

كيف يمكنني اكتشاف إدخال لوحة المفاتيح في برنامج Python النصي الذي يتم تشغيله من الجهاز؟

تم النشر بتاريخ 2024-12-21
تصفح:401

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

كيفية اكتشاف إدخال لوحة المفاتيح في البرنامج النصي من الجهاز؟

التقاط المفتاح المتزامن / الحظر:

إدخال بسيط أو إدخال أولي، حظر دالة تقوم بإرجاع النص الذي كتبه المستخدم بمجرد الضغط على السطر الجديد.

typedString = raw_input()

وظيفة حظر بسيطة تنتظر قيام المستخدم بالضغط على مفتاح واحد، ثم تقوم بإرجاع هذا المفتاح

class _Getch:
 """Gets a single character from standard input.  Does not echo to the
screen. From http://code.activestate.com/recipes/134892/"""
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:
"""
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.
"""
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 & 0x000000FF)


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

  return k

التقاط المفتاح غير المتزامن:

رد اتصال يتم استدعاؤه باستخدام المفتاح المضغوط عندما يكتب المستخدم مفتاحًا في موجه الأوامر، حتى عند كتابة الأشياء في مترجم فوري (مسجل لوحة المفاتيح)

لم يتم تنفيذ عمليات رد الاتصال بعد.

رد اتصال يتم استدعاؤه بالنص المكتوب بعد أن يضغط المستخدم على زر الإدخال (مسجل مفاتيح أقل في الوقت الفعلي)

لم يتم تنفيذ عمليات رد الاتصال بعد.

رد اتصال يتم استدعاؤه مع الضغط على المفاتيح عند تشغيل البرنامج (على سبيل المثال، في للحلقة أو أثناء الحلقة)

Windows:

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 = ""

    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("Capture is already going")

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

الاقتراع:

يريد المستخدم ببساطة أن يكون قادرًا على القيام بشيء ما عند الضغط على مفتاح، دون الحاجة إلى انتظار هذا المفتاح (لذلك لا ينبغي أن يكون هذا -الحظر). وبالتالي فإنهم يستدعون وظيفة poll() والتي تقوم إما بإرجاع مفتاح أو إرجاع لا شيء. يمكن أن يكون هذا إما فاقدًا (إذا استغرق وقتًا طويلاً بين الاستقصاء، فيمكن أن يفوتك مفتاح) أو غير فاقد (سيقوم القائم بالاستقصاء بتخزين سجل جميع المفاتيح التي تم الضغط عليها، لذلك عندما تطلبها وظيفة الاستقصاء () سيتم إرجاعها دائمًا بالترتيب الذي تم الضغط عليه).

Windows وOS X (وربما Linux):

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] & ~termios.ICANON & ~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)
أحدث البرنامج التعليمي أكثر>

تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.

Copyright© 2022 湘ICP备2022001581号-3