」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 如何檢測從終端運行的 Python 腳本中的鍵盤輸入?

如何檢測從終端運行的 Python 腳本中的鍵盤輸入?

發佈於2024-12-21
瀏覽:107

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

如何從終端檢測腳本中的鍵盤輸入?

同步/阻塞按鍵擷取:

簡單輸入或 raw_input,阻塞函數,一旦使用者按下換行符,就會傳回使用者輸入的文字。

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

非同步按鍵擷取:

每當使用者在命令提示字元中鍵入按鍵時,即使在解釋器(鍵盤記錄器)中鍵入內容,也會透過按下的按鍵呼叫回調

回呼尚未實現。

用戶按 Enter 鍵後使用鍵入的文本調用的回調(a較少的實時鍵盤記錄器)

回調尚未實現。

程式運行時(例如,在for 循環中)按下按鍵時調用的回調或while 循環)

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() 函數,該函數要么返回一個鍵,要么返回 None。這可以是有損的(如果它們在輪詢之間花費太長時間,它們可能會錯過一個鍵)或非有損的(輪詢器將存儲所有按下的鍵的歷史記錄,因此當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)
最新教學 更多>
  • 我可以將加密從McRypt遷移到OpenSSL,並使用OpenSSL遷移MCRYPT加密數據?
    我可以將加密從McRypt遷移到OpenSSL,並使用OpenSSL遷移MCRYPT加密數據?
    將我的加密庫從mcrypt升級到openssl 問題:是否可以將我的加密庫從McRypt升級到OpenSSL?如果是這樣,如何? 答案:是的,可以將您的Encryption庫從McRypt升級到OpenSSL。 可以使用openssl。 附加說明: [openssl_decrypt()函數要求...
    程式設計 發佈於2025-05-21
  • Java為何無法創建泛型數組?
    Java為何無法創建泛型數組?
    通用陣列創建錯誤 arrayList [2]; JAVA報告了“通用數組創建”錯誤。為什麼不允許這樣做? 答案:Create an Auxiliary Class:public static ArrayList<myObject>[] a = new ArrayList<my...
    程式設計 發佈於2025-05-21
  • Java開發者如何保護數據庫憑證免受反編譯?
    Java開發者如何保護數據庫憑證免受反編譯?
    在java 在單獨的配置文件保護數據庫憑證的最有效方法中存儲憑據是將它們存儲在單獨的配置文件中。該文件可以在運行時加載,從而使登錄數據從編譯的二進製文件中遠離。 使用prevereness class import java.util.prefs.preferences; 公共類示例{ 首選...
    程式設計 發佈於2025-05-21
  • 大批
    大批
    [2 數組是對象,因此它們在JS中也具有方法。 切片(開始):在新數組中提取部分數組,而無需突變原始數組。 令ARR = ['a','b','c','d','e']; // USECASE:提取直到索引作...
    程式設計 發佈於2025-05-21
  • Python讀取CSV文件UnicodeDecodeError終極解決方法
    Python讀取CSV文件UnicodeDecodeError終極解決方法
    在試圖使用已內置的CSV模塊讀取Python中時,CSV文件中的Unicode Decode Decode Decode Decode decode Error讀取,您可能會遇到錯誤的錯誤:無法解碼字節 在位置2-3中:截斷\ uxxxxxxxx逃脫當CSV文件包含特殊字符或Unicode的路徑逃...
    程式設計 發佈於2025-05-21
  • 在Ubuntu/linux上安裝mysql-python時,如何修復\“ mysql_config \”錯誤?
    在Ubuntu/linux上安裝mysql-python時,如何修復\“ mysql_config \”錯誤?
    mysql-python安裝錯誤:“ mysql_config找不到”“ 由於缺少MySQL開發庫而出現此錯誤。解決此問題,建議在Ubuntu上使用該分發的存儲庫。使用以下命令安裝Python-MysqldB: sudo apt-get安裝python-mysqldb sudo pip in...
    程式設計 發佈於2025-05-21
  • 版本5.6.5之前,使用current_timestamp與時間戳列的current_timestamp與時間戳列有什麼限制?
    版本5.6.5之前,使用current_timestamp與時間戳列的current_timestamp與時間戳列有什麼限制?
    在時間戳列上使用current_timestamp或MySQL版本中的current_timestamp或在5.6.5 此限制源於遺留實現的關注,這些限制需要對當前的_timestamp功能進行特定的實現。 創建表`foo`( `Productid` int(10)unsigned not ...
    程式設計 發佈於2025-05-21
  • 如何使用Python理解有效地創建字典?
    如何使用Python理解有效地創建字典?
    在python中,詞典綜合提供了一種生成新詞典的簡潔方法。儘管它們與列表綜合相似,但存在一些顯著差異。 與問題所暗示的不同,您無法為鑰匙創建字典理解。您必須明確指定鍵和值。 For example:d = {n: n**2 for n in range(5)}This creates a dict...
    程式設計 發佈於2025-05-21
  • 如何使用組在MySQL中旋轉數據?
    如何使用組在MySQL中旋轉數據?
    在關係數據庫中使用mySQL組使用mySQL組進行查詢結果,在關係數據庫中使用MySQL組,轉移數據的數據是指重新排列的行和列的重排以增強數據可視化。在這裡,我們面對一個共同的挑戰:使用組的組將數據從基於行的基於列的轉換為基於列。 Let's consider the following ...
    程式設計 發佈於2025-05-21
  • 如何將PANDAS DataFrame列轉換為DateTime格式並按日期過濾?
    如何將PANDAS DataFrame列轉換為DateTime格式並按日期過濾?
    將pandas dataframe列轉換為dateTime格式示例:使用column(mycol)包含以下格式的以下dataframe,以自定義格式:})指定的格式參數匹配給定的字符串格式。轉換後,MyCol列現在將包含DateTime對象。 date date filtering > = ...
    程式設計 發佈於2025-05-21
  • CSS強類型語言解析
    CSS強類型語言解析
    您可以通过其强度或弱输入的方式对编程语言进行分类的方式之一。在这里,“键入”意味着是否在编译时已知变量。一个例子是一个场景,将整数(1)添加到包含整数(“ 1”)的字符串: result = 1 "1";包含整数的字符串可能是由带有许多运动部件的复杂逻辑套件无意间生成的。它也可以是故意从单个真理...
    程式設計 發佈於2025-05-21
  • 如何使用PHP從XML文件中有效地檢索屬性值?
    如何使用PHP從XML文件中有效地檢索屬性值?
    從php $xml = simplexml_load_file($file); foreach ($xml->Var[0]->attributes() as $attributeName => $attributeValue) { echo $attributeName,...
    程式設計 發佈於2025-05-21
  • C++成員函數指針正確傳遞方法
    C++成員函數指針正確傳遞方法
    如何將成員函數置於c [&& && && && && && && && && && &&&&&&&&&&&&&&&&&&&&&&&華儀的函數時,在接受成員函數指針的函數時,要在函數上既要提供指針又可以提供指針和指針到函數的函數。需要具有一定簽名的功能指針。要通過成員函數,您需要同時提供對象指針(此...
    程式設計 發佈於2025-05-21
  • HTML格式標籤
    HTML格式標籤
    HTML 格式化元素 **HTML Formatting is a process of formatting text for better look and feel. HTML provides us ability to format text without us...
    程式設計 發佈於2025-05-21

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3