python - 在Mac上使用Python监听键盘并遇到AttributeError : CFMachPortCreateRunLoopSource

标签 python macos

我正在尝试找到一种方法来量化我分心的频率。然而,以下技术有缺陷,但至少比没有好。我决定尝试计算计算机中的击键和鼠标点击次数。当我运行以下 python 代码时,我可以听到我的 Mac 键盘的声音,前提是我从 Mac Terminal 执行此操作并使用 sudo:

import keyboard
def count_key_strokes():
    while True:
        b = keyboard.read_key()
        print (b)

但是,keyboard 模块不是为 Mac 上的鼠标点击而编写的,因此我必须使用不同的模块,如下所示:

from pynput import mouse
def on_click(x, y, button, pressed):
    if not pressed:
        return False


def count_mouse():
    d = 0
    while True:


        with mouse.Listener(
                on_click=on_click,
                ) as listener:
            listener.join()
            d += 1
            print (d)

为了同时运行这两个程序,我必须将它们连接在一起,如下所示:

import threading
''code here
threading.Thread(target=count_mouse).start()
threading.Thread(target=count_key_strokes).start()

但是,当我从 Terminal 运行该代码时,使用:

sudo python3 count_keystrokes.py

我收到以下错误消息,但不明白原因:

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/keyboard/__init__.py", line 292, in listen
    _os_keyboard.listen(self.direct_callback)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/keyboard/_darwinkeyboard.py", line 431, in listen
    KeyEventListener(callback).run()
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/keyboard/_darwinkeyboard.py", line 366, in run
    loopsource = Quartz.CFMachPortCreateRunLoopSource(None, self.tap, 0)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/objc/_lazyimport.py", line 163, in __getattr__
    raise AttributeError(name)
AttributeError: CFMachPortCreateRunLoopSource

更新

真正的程序只是稍微复杂一些。真正的程序会跟踪时间,并且仅在某个应用程序位于最前面时才计算击键和鼠标点击。无论如何,20 分钟后我的电脑 (MacBookPro 2015) 总是会变慢得难以忍受。可以肯定的是,这个程序是罪魁祸首,因为当我终止它时,一切都会立即恢复正常。我的第一个解决方法是每 2 分钟重置一次程序,但这不起作用。 20 分钟后,计算机的速度仍然慢得令人难以忍受。

import keyboard, threading
from pynput import mouse
import time
from AppKit import NSWorkspace
#
totals = []
clicks = 0

def count_keystrokes():
    global clicks
    keystrokes = 0
    elapsed = 0
    minutes = 0
    total_elapsed = 0
    all_time = lambda x, y, z: y + (z - x) if x != 0 else 0

    while True:
        active_app = NSWorkspace.sharedWorkspace().activeApplication()
        front_app = active_app["NSApplicationName"]
        if front_app == 'PyCharm':
            if elapsed == 0:
                elapsed = time.time()

            b = keyboard.read_key()
            keystrokes += 1

        else:
            if elapsed > 0:
                total_elapsed += (time.time() - elapsed)
                elapsed = 0

        if all_time(elapsed, total_elapsed, time.time()) > 30:
            minutes += 1
            print (f"{minutes}  {keystrokes + clicks}")
            # print (keystrokes + clicks)
            total_elapsed = 0
            elapsed = 0
            keystrokes = 0
            clicks = 0



def on_click(x, y, button, pressed):
    if not pressed:
        return False


def main():
    global clicks
    time1 = time.time()
    thread = threading.Thread(target=count_keystrokes)
    thread.daemon = True
    thread.start()


    while True:
        clicks = 0
        with mouse.Listener(on_click=on_click) as listener:
            listener.join()
            frontmost = NSWorkspace.sharedWorkspace().activeApplication()
            if frontmost["NSApplicationName"] == 'PyCharm':
                clicks += 1
            if time.time() - time1 > 120:
                return


    thread.join()


while True:
    main()

    print ('main program exited')
    time.sleep(1)

更新

问题肯定是线程。仅使用键盘监听运行的程序运行良好,并且不会降低计算机速度。

最佳答案

pynput.keyboard.Listenerpynput.mouse.Listener 都是 threading.Thread 的子类,因此不需要显式地声明完全使用线程。

with 语句,如 the documentation 中所述,只是简写:

listener.start()
try:
    with_statements()
finally:
    listener.stop()

而且没有必要。

脚本的简化版本可能会这样编写:

from pynput import keyboard, mouse


def on_press(key):
    # A key has been pressed
    pass


def on_click(x, y, button, pressed):
    if pressed:
        # A mouse button has been clicked
        pass


with keyboard.Listener(on_press=on_press) as kl, \
        mouse.Listener(on_click=on_click) as ml:
    kl.join()
    ml.join()

关于python - 在Mac上使用Python监听键盘并遇到AttributeError : CFMachPortCreateRunLoopSource,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52136168/

相关文章:

python - pandas 根据条件执行操作 - 不同的方式和最佳实践?

在 OSX 上编译错误,但在 Windows 或 Linux 上没有编译错误

macos - 无法在 Mac OS 10.7 上安装 netbeans

python - 需要关闭 python 套接字/在我的开发环境中查找当前正在运行的服务器

objective-c - stringWithContentsOfURL 是否使用系统代理设置?

ios - 应用程序加载器iOS问题

python 幽灵脚本 : RuntimeError: Can not find Ghostscript library (libgs)

python - 'NoneType' 对象没有属性 'add'

python - 使用cherry.py调用函数

python - scikit-learn kmeans自定义距离