杰瑞科技汇

python blockinput

Of course. The term "block input" in Python refers to preventing the user from sending keyboard and mouse events to the operating system. This is useful for creating things like automated scripts, games, or kiosk applications where you don't want the user to interfere.

python blockinput-图1
(图片来源网络,侵删)

There is no single, built-in Python module that does this for all operating systems. The method you use depends on whether you're on Windows, macOS, or Linux.

Here’s a complete guide covering all three major platforms.


Summary: Which Method to Use?

Operating System Recommended Method Python Library
Windows ctypes to call BlockInput from user32.dll ctypes (built-in)
macOS pynput to stop and start a local listener pynput (install via pip)
Linux xinput command-line tool (requires X11) subprocess (built-in)

Windows (Using ctypes)

On Windows, the most direct and native way is to call the BlockInput function from the user32.dll system library using Python's ctypes module, which is included with Python.

Important Note: BlockInput is a powerful function. It will block all input, including Ctrl+Alt+Del and other system-level shortcuts. Use it with caution.

python blockinput-图2
(图片来源网络,侵删)

How it Works:

The BlockInput function takes a single boolean argument:

  • True: Blocks all keyboard and mouse input.
  • False: Unblocks all input.

Code Example:

import ctypes
import time
# The BlockInput function is in user32.dll
user32 = ctypes.windll.user32
# Define the function signature (it takes a BOOL and returns a BOOL)
# BOOL BlockInput(BOOL fBlockIt);
user32.BlockInput.argtypes = [ctypes.c_bool]
user32.BlockInput.restype = ctypes.c_bool
def block_input_windows(block: bool):
    """
    Blocks or unblocks all keyboard and mouse input on Windows.
    Args:
        block (bool): True to block, False to unblock.
    """
    result = user32.BlockInput(block)
    if result:
        print(f"Input {'blocked' if block else 'unblocked'} successfully.")
    else:
        print(f"Failed to {'block' if block else 'unblock'} input.")
if __name__ == "__main__":
    print("Blocking input for 5 seconds...")
    block_input_windows(True)
    # You can't interact with the console or any other window now
    time.sleep(5) 
    print("Unblocking input.")
    block_input_windows(False)
    input("Press Enter to exit...") # This will now work

macOS (Using pynput)

On macOS, there isn't a simple one-to-one equivalent to Windows' BlockInput. The most reliable cross-platform library for this task is pynput. The strategy is to start a "listener" that captures all input but does nothing with it, effectively consuming it before it reaches any other application.

Installation:

First, you need to install the library:

pip install pynput

How it Works:

  1. You create a pynput listener for both the mouse and keyboard.
  2. You define "on_move", "on_click", "on_press", etc., functions that simply pass (do nothing).
  3. You start the listener in a separate thread.
  4. To "unblock", you simply stop the listener thread.

Code Example:

import time
from pynput import mouse, keyboard
# This flag will be used to control the listener
is_blocking = False
def on_move(x, y):
    """Called when the mouse is moved."""
    pass
def on_click(x, y, button, pressed):
    """Called when the mouse is clicked."""
    pass
def on_scroll(x, y, dx, dy):
    """Called when the mouse is scrolled."""
    pass
def on_press(key):
    """Called when a key is pressed."""
    pass
def on_release(key):
    """Called when a key is released."""
    pass
# Create listener objects
mouse_listener = mouse.Listener(on_move=on_move, on_click=on_click, on_scroll=on_scroll)
keyboard_listener = keyboard.Listener(on_press=on_press, on_release=on_release)
def block_input_macos(block: bool):
    """
    Blocks or unblocks all input on macOS using pynput listeners.
    Args:
        block (bool): True to block, False to unblock.
    """
    global is_blocking
    global mouse_listener, keyboard_listener
    if block and not is_blocking:
        print("Blocking input...")
        # Start the listeners in non-blocking mode
        mouse_listener.start()
        keyboard_listener.start()
        is_blocking = True
    elif not block and is_blocking:
        print("Unblocking input...")
        # Stop the listeners
        mouse_listener.stop()
        keyboard_listener.stop()
        is_blocking = False
    else:
        print(f"Input is already {'blocked' if is_blocking else 'unblocked'}.")
if __name__ == "__main__":
    try:
        print("Blocking input for 5 seconds...")
        block_input_macos(True)
        # You can't interact with the console or any other window now
        time.sleep(5) 
        print("Unblocking input.")
        block_input_macos(False)
        input("Press Enter to exit...") # This will now work
    except KeyboardInterrupt:
        # Ensure listeners are stopped if the script is interrupted
        block_input_macos(False)
        print("\nScript interrupted. Input unblocked.")

Linux (Using xinput)

On Linux with a graphical environment (X11), you can use the xinput command-line utility to disable specific input devices like your mouse or keyboard.

python blockinput-图3
(图片来源网络,侵删)

Prerequisite: You need to have xinput installed. If not, you can install it with your system's package manager:

  • Debian/Ubuntu: sudo apt-get install xinput
  • Fedora/CentOS: sudo dnf install xinput
  • Arch Linux: sudo pacman -S xinput

How it Works:

  1. First, find the ID of your device using xinput list.
  2. Then, use xinput disable <device_id> to block it and xinput enable <device_id> to unblock it.

Code Example:

import subprocess
import time
import re
def get_device_id(device_name: str):
    """
    Finds the xinput device ID for a given device name.
    Returns the ID or None if not found.
    """
    try:
        # Run the xinput list command
        result = subprocess.run(['xinput', 'list'], capture_output=True, text=True, check=True)
        # Search for the device name and capture its ID
        # Example line: "↳ SynPS/2 Synaptics TouchPad   id=12   [slave  pointer  (2)]"
        match = re.search(rf'{re.escape(device_name)}\s+id=(\d+)', result.stdout)
        if match:
            return int(match.group(1))
        return None
    except (subprocess.CalledProcessError, FileNotFoundError):
        print("Error: 'xinput' command not found. Is it installed and in your PATH?")
        return None
def block_input_linux(device_id: int, block: bool):
    """
    Enables or disables a specific xinput device.
    Args:
        device_id (int): The ID of the device to control.
        block (bool): True to disable (block), False to enable (unblock).
    """
    command = ['xinput', 'disable' if block else 'enable', str(device_id)]
    try:
        subprocess.run(command, check=True)
        action = "disabled" if block else "enabled"
        print(f"Device {device_id} {action}.")
    except subprocess.CalledProcessError as e:
        print(f"Failed to {'disable' if block else 'enable'} device {device_id}. Error: {e}")
if __name__ == "__main__":
    # Find the IDs for your mouse and keyboard
    # Common names are "Logitech USB Optical Mouse", "AT Translated Set 2 keyboard", etc.
    # Use `xinput list` in your terminal to find the exact names for your devices.
    mouse_name = "Logitech USB Optical Mouse" 
    keyboard_name = "AT Translated Set 2 keyboard"
    mouse_id = get_device_id(mouse_name)
    keyboard_id = get_device_id(keyboard_name)
    if not mouse_id or not keyboard_id:
        print("Could not find one or both devices. Exiting.")
    else:
        print(f"Found Mouse ID: {mouse_id}, Keyboard ID: {keyboard_id}")
        print("\nBlocking input for 5 seconds...")
        block_input_linux(mouse_id, True)
        block_input_linux(keyboard_id, True)
        # You can't use the mouse or keyboard now
        time.sleep(5)
        print("\nUnblocking input.")
        block_input_linux(mouse_id, False)
        block_input_linux(keyboard_id, False)
        input("Press Enter to exit...") # This will now work

Important Considerations and Caveats

  1. Permissions: On Linux and macOS, your Python script might need elevated permissions (e.g., sudo) to be able to block system-level input.
  2. Accessibility Permissions (macOS): When you run a script that uses pynput for the first time, macOS will likely prompt you to grant it "Accessibility" permissions in System Settings > Privacy & Security. You must allow this for the script to work.
  3. No Perfect Solution for Linux Wayland: The xinput method works on X11, which is the traditional display server for Linux. However, many modern Linux distributions use Wayland, which has a different security model and doesn't allow a simple process to globally block input in the same way. For Wayland, you would need a more complex solution using the libinput or wlr-input-inhibitor protocols, which are beyond the scope of a simple script.
  4. Global vs. Application: These methods block input system-wide. If you only want to block input within a specific Pygame or Tkinter window, those libraries have their own event loop and focus management that can handle this more gracefully.
分享:
扫描分享到社交APP
上一篇
下一篇