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

Linda Hamilton
發布: 2024-10-29 17:37:02
原創
739 人瀏覽過

How can you detect keyboard input in Python scripts running from the terminal?

從終端機在Python 腳本中實現鍵盤輸入檢測

要在Python 腳本運行時檢測來自終端的鍵盤輸入,您有多個選項,每個選項都有其優點和限制:

同步/阻塞按鍵捕獲

  • 簡單input() 或raw_input():停止腳本執行直到使用者按Enter 鍵的Python 函數,提供鍵入的文字。
<code class="python">typedString = raw_input()</code>
登入後複製
  • 簡單的阻塞按鍵捕捉:
<code class="python">import msvcrt
k=msvcrt.getch()</code>
登入後複製

非同步按

  • 非同步按按鍵時回調
  • :
<code class="python">import win32api, time
from win32api import STD_INPUT_HANDLE
from win32console import GetStdHandle, KEY_EVENT, ENABLE_LINE_INPUT, ENABLE_ECHO_INPUT, ENABLE_PROCESSED_INPUT

from keyPress import KeyPress

class CaptureLines():
    def __init__(self):
        self.isCapturingInputLines = False

        self.inputLinesHookCallback = CFUNCTYPE(c_int)(self.inputLinesHook)
        self.pyosInputHookPointer = c_void_p.in_dll(pythonapi, "PyOS_InputHook")
        self.originalPyOsInputHookPointerValue = self.pyosInputHookPointer.value

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


    def inputLinesHook(self):
        self.readHandle.SetConsoleMode(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT)
        inputChars = self.readHandle.ReadConsole(10000000)
        self.readHandle.SetConsoleMode(ENABLE_LINE_INPUT|ENABLE_PROCESSED_INPUT)

        if inputChars == "\r\n":
            KeyPress("\n")
            return 0

        inputChars = inputChars[:-2]

        inputChars += "\n"

        for c in inputChars:
            KeyPress(c)

        self.inputCallback(inputChars)

        return 0</code>
登入後複製

輪詢
  • 簡單按鍵捕獲,無阻塞
  • :
<code class="python">import win32api, time
from win32api import STD_INPUT_HANDLE
from win32console import GetStdHandle, KEY_EVENT, ENABLE_LINE_INPUT, ENABLE_PROCESSED_INPUT

class KeyAsyncReader():
    def __init__(self):
        self.readHandle = GetStdHandle(STD_INPUT_HANDLE)
        self.readHandle.SetConsoleMode(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT)

    def poll(self):
        return self.readHandle.ReadConsoleInput()</code>
登入後複製

機器人
  • 以程式方式觸發鍵盤事件
  • :
<code class="python">import ctypes
from ctypes import wintypes
import time

user32 = ctypes.WinDLL('user32', use_last_error=True)

INPUT_MOUSE    = 0
INPUT_KEYBOARD = 1
INPUT_HARDWARE = 2

KEYEVENTF_EXTENDEDKEY = 0x0001
KEYEVENTF_KEYUP       = 0x0002
KEYEVENTF_UNICODE     = 0x0004
KEYEVENTF_SCANCODE    = 0x0008

MAPVK_VK_TO_VSC = 0

# C struct definitions
wintypes.ULONG_PTR = wintypes.WPARAM

SendInput = ctypes.windll.user32.SendInput

PUL = ctypes.POINTER(ctypes.c_ulong)

class KEYBDINPUT(ctypes.Structure):
    _fields_ = ((&quot;wVk&quot;,         wintypes.WORD),
                (&quot;wScan&quot;,       wintypes.WORD),
                (&quot;dwFlags&quot;,     wintypes.DWORD),
                (&quot;time&quot;,        wintypes.DWORD),
                (&quot;dwExtraInfo&quot;, wintypes.ULONG_PTR))

class MOUSEINPUT(ctypes.Structure):
    _fields_ = ((&quot;dx&quot;,          wintypes.LONG),
                (&quot;dy&quot;,          wintypes.LONG),
                (&quot;mouseData&quot;,   wintypes.DWORD),
                (&quot;dwFlags&quot;,     wintypes.DWORD),
                (&quot;time&quot;,        wintypes.DWORD),
                (&quot;dwExtraInfo&quot;, wintypes.ULONG_PTR))

class HARDWAREINPUT(ctypes.Structure):
    _fields_ = ((&quot;uMsg&quot;,    wintypes.DWORD),
                (&quot;wParamL&quot;, wintypes.WORD),
                (&quot;wParamH&quot;, wintypes.WORD))

class INPUT(ctypes.Structure):
    class _INPUT(ctypes.Union):
        _fields_ = ((&quot;ki&quot;, KEYBDINPUT),
                    (&quot;mi&quot;, MOUSEINPUT),
                    (&quot;hi&quot;, HARDWAREINPUT))
    _anonymous_ = (&quot;_input&quot;,)
    _fields_ = ((&quot;type&quot;,   wintypes.DWORD),
                (&quot;_input&quot;, _INPUT))

LPINPUT = ctypes.POINTER(INPUT)

def _check_count(result, func, args):
    if result == 0:
        raise ctypes.WinError(ctypes.get_last_error())
    return args

user32.SendInput.errcheck = _check_count
user32.SendInput.argtypes = (wintypes.UINT, # nInputs
                             LPINPUT,       # pInputs
                             ctypes.c_int)  # cbSize

def KeyDown(unicodeKey):
    key, unikey, uniflag = GetKeyCode(unicodeKey)
    x = INPUT( type=INPUT_KEYBOARD, ki= KEYBDINPUT( key, unikey, uniflag, 0))
    user32.SendInput(1, ctypes.byref(x), ctypes.sizeof(x))

def KeyUp(unicodeKey):
    key, unikey, uniflag = GetKeyCode(unicodeKey)
    extra = ctypes.c_ulong(0)
    x = INPUT( type=INPUT_KEYBOARD, ki= KEYBDINPUT( key, unikey, uniflag | KEYEVENTF_KEYUP, 0))
    user32.SendInput(1, ctypes.byref(x), ctypes.sizeof(x))

def KeyPress(unicodeKey):
    time.sleep(0.0001)
    KeyDown(unicodeKey)
    time.sleep(0.0001)
    KeyUp(unicodeKey)
    time.sleep(0.0001)


def GetKeyCode(unicodeKey):
    k = unicodeKey
    curKeyCode = 0
    if k == &quot;up&quot;: curKeyCode = 0x26
    elif k == &quot;down&quot;: curKeyCode = 0x28
    elif k == &quot;left&quot;: curKeyCode = 0x25
    elif k == &quot;right&quot;: curKeyCode = 0x27
    elif k == &quot;home&quot;: curKeyCode = 0x24
    elif k == &quot;end&quot;: curKeyCode = 0x23
    elif k == &quot;insert&quot;: curKeyCode = 0x2D
    elif k == &quot;pgup&quot;: curKeyCode = 0x21
    elif k == &quot;pgdn&quot;: curKeyCode = 0x22
    elif k == &quot;delete&quot;: curKeyCode = 0x2E
    elif k == &quot;\n&quot;: curKeyCode = 0x0D

    if curKeyCode == 0:
        return 0, int(unicodeKey.encode(&quot;hex&quot;), 16), KEYEVENTF_UNICODE
    else:
        return curKeyCode, 0, 0</code>
登入後複製

以上是如何檢測從終端運行的 Python 腳本中的鍵盤輸入?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板