Skip to main content

监视和控制用户输入设备

项目描述

输入法

该库允许您控制和监视输入设备。

目前,支持鼠标和键盘输入和监控。

有关完整文档,请参见此处

控制鼠标

像这样使用pynput.mouse.Controller

from pynput.mouse import Button, Controller

mouse = Controller()

# Read pointer position
print('The current pointer position is {0}'.format(
    mouse.position))

# Set pointer position
mouse.position = (10, 20)
print('Now we have moved it to {0}'.format(
    mouse.position))

# Move pointer relative to current position
mouse.move(5, -5)

# Press and release
mouse.press(Button.left)
mouse.release(Button.left)

# Double click; this is different from pressing and releasing
# twice on macOS
mouse.click(Button.left, 2)

# Scroll two steps down
mouse.scroll(0, 2)

监控鼠标

像这样使用pynput.mouse.Listener

from pynput import mouse

def on_move(x, y):
    print('Pointer moved to {0}'.format(
        (x, y)))

def on_click(x, y, button, pressed):
    print('{0} at {1}'.format(
        'Pressed' if pressed else 'Released',
        (x, y)))
    if not pressed:
        # Stop listener
        return False

def on_scroll(x, y, dx, dy):
    print('Scrolled {0} at {1}'.format(
        'down' if dy < 0 else 'up',
        (x, y)))

# Collect events until released
with mouse.Listener(
        on_move=on_move,
        on_click=on_click,
        on_scroll=on_scroll) as listener:
    listener.join()

# ...or, in a non-blocking fashion:
listener = mouse.Listener(
    on_move=on_move,
    on_click=on_click,
    on_scroll=on_scroll)
listener.start()

鼠标侦听器是threading.Thread,所有回调都将从线程调用。

从任何地方调用pynput.mouse.Listener.stop,引发StopException或从回调中返回False以停止侦听器。

当使用上面的非阻塞版本时,当前线程将继续执行。这在与其他包含主循环的 GUI 框架集成时可能是必需的,但是当从脚本运行时,这将导致程序立即终止。

鼠标监听线程

侦听器回调直接从某些平台上的操作线程调用,特别是Windows

这意味着不应从回调调用长时间运行的过程和阻塞操作,因为这可能会冻结所有进程的输入。

一种可能的解决方法是将传入的消息发送到队列,并让单独的线程处理它们。

处理鼠标侦听器错误

如果回调处理程序引发异常,则侦听器将停止。由于回调在专用线程中运行,因此不会自动重新引发异常。

要收到有关回调错误的通知,请在侦听器实例上调用Thread.join :

from pynput import mouse

class MyException(Exception): pass

def on_click(x, y, button, pressed):
    if button == mouse.Button.left:
        raise MyException(button)

# Collect events until released
with mouse.Listener(
        on_click=on_click) as listener:
    try:
        listener.join()
    except MyException as e:
        print('{0} was clicked'.format(e.args[0]))

切换监听鼠标监听器的事件

一旦调用了pynput.mouse.Listener.stop,就无法重新启动侦听器,因为侦听器是threading.Thread的实例。

如果您的应用程序需要切换侦听事件,您必须添加一个内部标志以在不需要时忽略事件,或者在恢复侦听时创建一个新侦听器。

监听鼠标监听器的同步事件

为了简化脚本,通过实用程序类pynput.mouse.Events支持同步事件侦听。此类支持以非阻塞方式读取单个事件,以及迭代所有事件。

要读取单个事件,请使用以下代码:

from pynput import mouse

# The event listener will be running in this block
with mouse.Events() as events:
    # Block at most one second
    event = events.get(1.0)
    if event is None:
        print('You did not interact with the mouse within one second')
    else:
        print('Received event {}'.format(event))

要遍历鼠标事件,请使用以下代码:

from pynput import mouse

# The event listener will be running in this block
with mouse.Events() as events:
    for event in events:
        if event.button == mouse.Button.right:
            break
        else:
            print('Received event {}'.format(event))

请注意,迭代器方法不支持非阻塞操作,因此它会等待至少一个鼠标事件。

这些事件将是在 pynput.mouse.Events中找到的内部类的实例。

确保 Windows 上的侦听器和控制器之间的坐标一致

最新版本的 _Windows_ 支持在系统扩展超过 100% 时运行扩展的旧版应用程序。这允许旧应用程序进行扩展,尽管外观模糊,并且避免了微小的、无法使用的用户界面。

不幸的是,这种缩放不适用于鼠标侦听器和控制器:侦听器将接收物理坐标,但控制器必须使用缩放坐标。

这可以通过告诉 Windows 您的应用程序支持 DPI 来解决。这是一个进程全局设置,所以 _pynput_ 无法自动完成。启用 DPI 感知,运行以下代码:

import ctypes


PROCESS_PER_MONITOR_DPI_AWARE = 2

ctypes.windll.shcore.SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE)

控制键盘

像这样使用pynput.keyboard.Controller

from pynput.keyboard import Key, Controller

keyboard = Controller()

# Press and release space
keyboard.press(Key.space)
keyboard.release(Key.space)

# Type a lower case A; this will work even if no key on the
# physical keyboard is labelled 'A'
keyboard.press('a')
keyboard.release('a')

# Type two upper case As
keyboard.press('A')
keyboard.release('A')
with keyboard.pressed(Key.shift):
    keyboard.press('a')
    keyboard.release('a')

# Type 'Hello World' using the shortcut type method
keyboard.type('Hello World')

监控键盘

像这样使用pynput.keyboard.Listener

from pynput import keyboard

def on_press(key):
    try:
        print('alphanumeric key {0} pressed'.format(
            key.char))
    except AttributeError:
        print('special key {0} pressed'.format(
            key))

def on_release(key):
    print('{0} released'.format(
        key))
    if key == keyboard.Key.esc:
        # Stop listener
        return False

# Collect events until released
with keyboard.Listener(
        on_press=on_press,
        on_release=on_release) as listener:
    listener.join()

# ...or, in a non-blocking fashion:
listener = keyboard.Listener(
    on_press=on_press,
    on_release=on_release)
listener.start()

键盘侦听器是threading.Thread,所有回调都将从线程调用。

从任何地方调用pynput.keyboard.Listener.stop,引发StopException 或从回调中返回False以停止侦听器。

传递给回调的关键参数是一个pynput.keyboard.Key,用于特殊键,一个pynput.keyboard.KeyCode用于普通字母数字键,或者只是None用于未知键。

当使用上面的非阻塞版本时,当前线程将继续执行。这在与其他包含主循环的 GUI 框架集成时可能是必需的,但是当从脚本运行时,这将导致程序立即终止。

键盘监听线程

侦听器回调直接从某些平台上的操作线程调用,特别是Windows

这意味着不应从回调调用长时间运行的过程和阻塞操作,因为这可能会冻结所有进程的输入。

一种可能的解决方法是将传入的消息发送到队列,并让单独的线程处理它们。

处理键盘侦听器错误

如果回调处理程序引发异常,则侦听器将停止。由于回调在专用线程中运行,因此不会自动重新引发异常。

要收到有关回调错误的通知,请在侦听器实例上调用Thread.join :

from pynput import keyboard

class MyException(Exception): pass

def on_press(key):
    if key == keyboard.Key.esc:
        raise MyException(key)

# Collect events until released
with keyboard.Listener(
        on_press=on_press) as listener:
    try:
        listener.join()
    except MyException as e:
        print('{0} was pressed'.format(e.args[0]))

切换事件监听键盘监听器

一旦调用了pynput.keyboard.Listener.stop,就无法重新启动侦听器,因为侦听器是threading.Thread的实例。

如果您的应用程序需要切换侦听事件,您必须添加一个内部标志以在不需要时忽略事件,或者在恢复侦听时创建一个新侦听器。

键盘监听器的同步事件监听

为了简化脚本,通过实用程序类pynput.keyboard.Events支持同步事件侦听。此类支持以非阻塞方式读取单个事件,以及迭代所有事件。

要读取单个事件,请使用以下代码:

from pynput import keyboard

# The event listener will be running in this block
with keyboard.Events() as events:
    # Block at most one second
    event = events.get(1.0)
    if event is None:
        print('You did not press a key within one second')
    else:
        print('Received event {}'.format(event))

要遍历键盘事件,请使用以下代码:

from pynput import keyboard

# The event listener will be running in this block
with keyboard.Events() as events:
    for event in events:
        if event.key == keyboard.Key.esc:
            break
        else:
            print('Received event {}'.format(event))

请注意,迭代器方法不支持非阻塞操作,因此它会等待至少一个键盘事件。

这些事件将是在 pynput.keyboard.Events中找到的内部类的实例。

全局热键

键盘监视器的一个常见用例是对全局热键做出反应。由于侦听器不维护任何状态,因此涉及多个键的热键必须将此状态存储在某处。

为此, pynput提供了类pynput.keyboard.HotKey。它包含两种更新状态的方法,旨在与键盘侦听器轻松互操作:pynput.keyboard.HotKey.presspynput.keyboard.HotKey.release可以直接作为侦听器回调传递。

预期用途如下:

from pynput import keyboard

def on_activate():
    print('Global hotkey activated!')

def for_canonical(f):
    return lambda k: f(l.canonical(k))

hotkey = keyboard.HotKey(
    keyboard.HotKey.parse('<ctrl>+<alt>+h'),
    on_activate)
with keyboard.Listener(
        on_press=for_canonical(hotkey.press),
        on_release=for_canonical(hotkey.release)) as l:
    l.join()

这将创建一个热键,然后使用侦听器更新其状态。一旦同时按下所有指定的键,就会调用on_activate 。

请注意,键在传递给HotKey实例之前通过pynput.keyboard.Listener.canonical传递。这是为了从键事件中删除任何修饰符状态,并使用多个物理按钮规范化修饰符。

pynput.keyboard.HotKey.parse方法是一个将快捷键字符串转换为键集合的便捷函数。请参阅其文档以获取更多信息。

要注册多个全局热键,请使用便捷类 pynput.keyboard.GlobalHotKeys

from pynput import keyboard

def on_activate_h():
    print('<ctrl>+<alt>+h pressed')

def on_activate_i():
    print('<ctrl>+<alt>+i pressed')

with keyboard.GlobalHotKeys({
        '<ctrl>+<alt>+h': on_activate_h,
        '<ctrl>+<alt>+i': on_activate_i}) as h:
    h.join()

发行说明

v1.7.6 (2022-01-01) - 各种修复

  • 允许将虚拟键代码传递给解析器以获取全局热键。

  • 在Xorg上异步停止录制上下文。

  • 不要将None传递给objc.objc_object。感谢叶君熙

  • 在uinput上按alt键时不要崩溃。感谢卡尔达斯洛佩斯

  • 为从后端实现派生的侦听器使用正确的选项前缀。感谢王宇

v1.7.5 (2021-11-19) - 各种修复

  • 更正了将侦听器配置为抑制系统事件时Xorg上的崩溃。感谢jpramosi

  • 改进了Windows上键盘控制器的处理。控制器现在对使用较低级别事件的应用程序进行了更大的更改。感谢布达克斯

  • 更新了macOS实现以使用新版本的pyobjc

v1.7.4 (2021-10-10) - 各种修复

  • 检测macOS上是否缺少权限。感谢丹麦人芬莱

  • 急切地从CoreFoundationQuartz导入符号。感 谢罗纳德·欧索伦

  • 改进了对dumpkeys实用程序的处理。感谢马库斯尼德曼

  • 删除了不明确的许可证文件。

v1.7.3 (2021-02-10) - 各种修复

  • 更正了Xorg上的键符处理;并非所有组都已加载,并且从未触发回退到我们的内部表。感谢菲利普克劳斯

  • 更新了用于macOS后端 的Quartz版本,以允许在Big Sur上安装pynput。感谢迈克尔·马登

  • 在Windows上添加了缺少的功能键。感谢戴夫阿特金森

  • 更正了macOS上鼠标控制器的滚动速度。感谢阿尔伯特泽耶

  • 更正了Xorg的媒体密钥。感谢加布里埃尔·N·托内塔

  • 更正了文档中的参数名称。感谢吉内斯耶利扎提

v1.7.2 (2020-12-21) - 更正了 uinput 键映射

  • 更正了uinput后​​端的虚拟键码到字符的映射 。

  • 更正了拼写错误。感谢Martin Michlmayr

  • 更正和改进的文档。

v1.7.1 (2020-08-30) - 更正的发行说明

  • 更正感谢对Xorg的任意 unicode 字符支持。

v1.7.0 (2020-08-30) - 一个新的后端以及许多新功能和错误修复

  • 当没有可用的X服务器时,为Linux添加了一个新的基于uinput的键盘后端。

  • 允许在Xorg后端输入任意 unicode 字符。感谢 gdiShun

  • 允许使用环境变量覆盖自动选择的后端,并添加一个虚拟后端。

  • 在Windows上添加了对鼠标侧键的支持。感谢丹尼尔科瓦里克

  • 增加了点击按键的便捷方法。

  • 允许在热键中指定原始虚拟键代码。

  • 改进了无法加载后端时的错误消息。

  • 在事件的字符串化中包含更多信息。

  • 将Events.get的返回值更正为文档指定的值。

  • 更正了键盘侦听器不在某些键盘布局上键入随机字符。

  • 更正了在Windows上按下某些键时操作系统报告它们已死但不存在组合版本的错误。

  • 改进的文档。

v1.6.8 (2020-02-28) - 各种修复

  • 更新了文档。

  • 更正了 lint 警告和测试。

  • 不要在argtypes中为win32函数使用内部类型;这使得它们无法被在同一运行时中运行的其他代码调用。

  • 在Windows上的事件中包含扫描码。感谢布达克斯

  • 正确地将转换应用于Windows上的滚动事件值。感谢DOCCA0

v1.6.7 (2020-02-17) - 各种修复

  • 在提供非整数增量时更正了macOS上的无限滚动。感谢伊万·蒙苏里·伊瓦涅斯

  • 更正了macOS上媒体键的控制器和侦听器处理。感谢伊万·蒙苏里·伊瓦涅斯

v1.6.6 (2020-01-23) - 修正热键文档

  • 简单pynput.keyboard.HotKey的代码示例现在可以工作了。感谢jfongattw

v1.6.5 (2020-01-08) - 更正了媒体键映射

  • 更正了macOS上的媒体键映射。感谢路易斯·纳赫蒂格尔

v1.6.4 (2020-01-03) - 再次更正导入

  • 更正了键盘控制器的导入。感谢rhystedstone

v1.6.3 (2019-12-28) - 再次更正导入

  • 更正了键盘控制器的导入。感谢马特艾弗森

v1.6.2 (2019-12-28) - 修正进口

  • 更正了键盘控制器的导入。感谢马特艾弗森

v1.6.1 (2019-12-27) - Windows更正

  • 更正了Windows上的全局热键。

  • 更正了Windows上键盘侦听器的按下/释放状态。感谢西格尔

v1.6.0 (2019-12-11) - 全局热键

  • 添加了对全局热键的支持。

  • 添加了对同步流式侦听器事件的支持。

v1.5.2 (2019-12-06) - 更正了Xorg的媒体密钥名称

  • 从Xorg键中删除了媒体标志。

v1.5.1 (2019-12-06) - 更正了macOS的媒体密钥名称

  • 更正了macOS上媒体键的属性名称。感谢ah3243

v1.5.0 (2019-12-04) - 各种改进

  • 更正了Windows上的键盘侦听器。感谢akiratakasakisegalionSpecialCharacter

  • 更正了在Windows上与修饰符组合时对某些特殊键(包括箭头键)的处理。感谢tuessetr

  • 更新了文档以包含有关Windows上 DPI 缩放的信息。感谢大卫-萨卡

  • 添加了对媒体键的实验性支持。感谢ShivamJokerStormTersteeg

v1.4.5 (2019-11-05) - 更正了Python 3.8上的错误

  • 更正了有关在macOS上的Python 3.8上 使用in运算符进行枚举的错误。

v1.4.4 (2019-09-24) - 实际上更正了 macOS 上的键盘侦听器

  • 包括提交以正确回退 CGEventKeyboardGetUnicodeString

  • 更正了Python 3.8上有关Enum使用的弃用警告。

v1.4.3 (2019-09-24) - 再次更正了 macOS 上的键盘监听器

  • 正确地回退到 CGEventKeyboardGetUnicodeString

  • 更新了文档。

v1.4.2 (2019-03-22) - 更正了 macOS 上的键盘监听器

  • macOS键盘侦听器中使用CGEventKeyboardGetUnicodeString发送正确的字符。

  • 在Xorg键盘侦听器中包含键符号而不是键代码。

  • 更正了日志记录以不包括预期的 StopException

  • 更新和更正了文档。

v1.4.1 (2018-09-07) - 日志记录

  • 记录侦听器回调引发的未处理异常。

v1.4 (2018-07-03) - 事件抑制

  • 增加了在收听时完全抑制事件的可能性。

  • 添加了对键入一些控制字符的支持。

  • 在OSX上添加了对鼠标拖动事件的支持。感谢丛林鼓

  • 在键盘侦听器事件中包含键代码。

  • 在启用num lock的情况下正确处理Xorg上的数字键盘。感谢TheoRet

  • 更正了Windows上当前线程键盘布局的处理。感 谢施迈塔林

  • 更正了Xorg上侦听器的停止。

  • 更正了 Xorg 上Xlib.keysymdef.xkb导入。感谢格兰多斯

v1.3.10 (2018-02-05) - 不要在Xephyr下崩溃

  • 当Xlib.display.Display.get_input_focus返回一个整数时不要崩溃,就像在Xephyr下运行时一样。感谢伊莱·斯凯格斯

v1.3.9 (2018-01-12) -在OSX上正确处理字母A

  • 更正了在OSX上生成键盘事件时对虚拟键代码的检查 。这解决了一个问题,即在显式按下 shift 的情况下按下A仍会键入一个小写字母。

v1.3.8 (2017-12-08) - 不要在OSX上的某些键盘布局上崩溃

  • 回退到另一种方法来检索OSX上的键盘布局。这有助于某些键盘布局,例如Chinese。感谢 haoflynet

v1.3.7 (2017-08-23) - Xorg更正

  • 包括用于Xorg的最多30 个鼠标按钮。

v1.3.6 (2017-08-13) - win32修正

  • 更正了Windows上虚假键盘事件的双重传递。

  • 更正了Windows上合成 unicode 键的处理。

v1.3.5 (2017-06-07) - 再次更正依赖关系

  • 还原1.3.3中的更改。

  • 更正了Linux上Python 2的平台说明符。

v1.3.4 (2017-06-05) - Xorg更正

  • 更正了Xorg上的值的边界检查。

v1.3.3 (2017-06-05) - 使依赖项不可选

  • 使平台依赖项成为非可选的。

v1.3.2 (2017-05-15) - 修复 Mac 上的按钮点击问题

  • 更正了先前版本的回归,即单击按钮会使Mac鼠标侦听器崩溃。

v1.3.1 (2017-05-12) - 修复了 Linux 上的未知按钮

  • 在Xorg鼠标侦听器中回退Button.unknown以获取未知鼠标按钮。

v1.3 (2017-04-10) - 平台特定功能

  • 添加了在Windows上停止事件传播的功能。这将防止事件到达其他应用程序。

  • 添加了在Windows上忽略事件的功能。对于键盘监视器干扰正常键盘事件的系统,这是一种解决方法。

  • 增加了在OSX上修改事件的能力。这允许在输入事件到达其他应用程序之前拦截和更改它们。

  • 更正了安装某些类型的第三方输入源时OSX上的崩溃。

v1.2 (2017-01-06) - 改进了错误处理

  • 允许捕获从侦听器回调中抛出的异常。这会更改 API,因为现在加入侦听器可能会引发未处理的异常,而未处理的异常将停止侦听器。

  • 增加了对Linux上数字键盘的支持。

  • 改进的文档。

  • 感谢jollyseangilleswijnker的投入!

v1.1.7 (2017-01-02) - 处理 Windows 上的中间按钮

  • 在Windows上侦听并发送中键鼠标点击。

v1.1.6 (2016-11-24) - 更正了按键的上下文管理器

  • 更正了pynput.keyboard.Controller.pressed中导致它永远不会释放键的错误。非常感谢托比·索斯韦尔!

v1.1.5 (2016-11-17) - 更正了 Linux 上的修饰键组合

  • 更正了修饰键的处理,使它们可以在 Linux上组合。

v1.1.4 (2016-10-30) - 小错误修正

  • 更正了GetKeyboardState失败时生成的错误。

  • 确保将 shift 状态应用于X上的借用键。

  • 使用pylint

v1.1.3 (2016-09-27) - 更改了 Xlib 后端库

  • 更改了Xlib库。

v1.1.2 (2016-09-26) - 添加了 Python 2 的缺失类型

  • Windows上的Python 2添加了缺失的LPDWORD

v1.1.1 (2016-09-26) - 修复了 Windows 上的监听器和控制器

  • 更正了Windows上的键盘侦听器。现在可以正确处理修改键和其他更改键盘状态的键。

  • 更正了Windows上的鼠标单击和释放。

  • 更正了代码示例。

v1.1 (2016-06-22) - Linux 上的简化使用

  • 传播在 Linux 上引发的导入错误,以帮助解决缺少的 Xlib模块。

  • 将 python3-xlib声明为Python 3对Linux的依赖。

v1.0.6 (2016-04-19) - 万向轮

  • 确保为所有 python 版本构建一个通用轮子。

v1.0.5 (2016-04-11) - 在 OSX 上拖动的修复

  • 更正了OSX上的拖动。

  • 为OSX添加了滚动速度常数以纠正缓慢的滚动速度。

v1.0.4 (2016-04-11) - 修复了在 Windows 上的点击和滚动

  • 更正了发送单击和滚动事件时鼠标输入字段的名称。

v1.0.3 (2016-04-05) - 修复了 Windows 上的 Python 3

  • 更正了 Windows上ctypes的使用。

v1.0.2 (2016-04-03) - 修复了线程标识符

  • 使用线程标识符来标识线程,而不是线程实例。

v1.0.1 (2016-04-03) - 修复 Python 3

  • 更正了阻止该库在Python 3上使用的错误。

v1.0 (2016-02-28) - 稳定版

  • 将许可证更改为LGPL

  • 更正了小错误和不一致。

  • 更正和扩展的文档。

v0.6 (2016-02-08) - 键盘监视器

  • 添加了对监控键盘的支持。

  • 更正车轮包装。

  • 更正了在某些情况下在X上停止侦听器时的死锁。

  • 更正了Mac OSX上的关键代码常量。

  • 不要拦截Mac OSX上的事件。

v0.5.1 (2016-01-26) - 不要死在死键上

  • 更正了对死键的处理。

  • 更正的文档。

v0.5 (2016-01-18) - 键盘修改器

  • 添加了对修饰符的支持。

v0.4 (2015-12-22) - 键盘控制器

  • 添加了键盘控制器。

v0.3 (2015-12-22) - 清理

  • pynput.mouse.Controller.Button移至顶层。

v0.2 (2015-10-28) - 初始版本

  • 支持在LinuxMac OSXWindows上控制鼠标。

  • 支持在LinuxMac OSXWindows上监视鼠标。