Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mouse listener crashes in Windows 11 (NotImplementedError) #614

Open
n-mou opened this issue Oct 19, 2024 · 12 comments
Open

Mouse listener crashes in Windows 11 (NotImplementedError) #614

n-mou opened this issue Oct 19, 2024 · 12 comments

Comments

@n-mou
Copy link

n-mou commented Oct 19, 2024

Description

Installed pynput in a new virtual environment and tried to track mouse and keyboard events. Keyboard presses were handled successfully but when a mouse event was triggered the program crashed with a NotImplementedError. I created a new main.py without the rest of my app's overhead and the same error happened. Searched for help in StackOverflow and got a snippet to track both mouse and keyboard events (to check if it was my code's fault) and the same error happened. Finally I moved out of the virtual environment in a clean Python install, added pynput through pip and run the snippet. The same error happened.

Platform and pynput version

  • Windows version: Windows 11 Home 23H2 22631.4317
  • Python version: Python 3.13.0 (tags/v3.13.0:60403a5, Oct 7 2024, 09:38:07) [MSC v.1941 64 bit (AMD64)] on win32
  • Pip version: 24.2
  • Pynput version: 1.7.7

To Reproduce

  • Install pynput either in a clean python install or in a virtual environment through pip
  • Try to run this code snippet:
from pynput.keyboard import Listener  as KeyboardListener
from pynput.mouse    import Listener  as MouseListener
from pynput.keyboard import Key
import logging
import sys

logging.basicConfig(filename=("log.txt"), level=logging.DEBUG, format='%(asctime)s: %(message)s')

def end_rec(key):
	logging.info(str(key))

def on_press(key):
	if key == Key.esc:
		sys.exit()
	logging.info(str(key))

def on_move(x, y):
	logging.info("Mouse moved to ({0}, {1})".format(x, y))

def on_click(x, y, button, pressed):
	if pressed:
		logging.info('Mouse clicked at ({0}, {1}) with {2}'.format(x, y, button))

def on_scroll(x, y, dx, dy):
	logging.info('Mouse scrolled at ({0}, {1})({2}, {3})'.format(x, y, dx, dy))


with MouseListener(on_click=on_click, on_scroll=on_scroll) as listener:
	with KeyboardListener(on_press=on_press) as listener:
		listener.join()
  • Press some keys (in this case: up, down, left and right) and move the cursor
  • Press Esc to quit the program
  • The resulting log.txt is:
2024-10-19 14:52:39,314: Key.up
2024-10-19 14:52:39,598: Key.down
2024-10-19 14:52:39,906: Key.left
2024-10-19 14:52:40,171: Key.right
2024-10-19 14:52:41,065: Unhandled exception in listener callback
Traceback (most recent call last):
  File "C:\Users\user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\pynput\_util\win32.py", line 386, in _handler
    converted = self._convert(code, msg, lpdata)
  File "C:\Users\user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\pynput\_util\win32.py", line 401, in _convert
    raise NotImplementedError()
NotImplementedError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\pynput\_util\__init__.py", line 229, in inner
    return f(self, *args, **kwargs)
  File "C:\Users\user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\pynput\_util\win32.py", line 390, in _handler
    self._handle(code, msg, lpdata)
    ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^
TypeError: '_thread._ThreadHandle' object is not callable
@zxt12138
Copy link

zxt12138 commented Nov 7, 2024

me too and I want known how old the version it is to avoid this issue

@moses-palmer
Copy link
Owner

Thank you for your report.

I cannot reproduce this error, but the stack trace seems to indicate that the problem may be internal changes to the Python threading library in Python 3.13 on Windows; self._handle is a method of the listener class, but it seems to have been overwritten by the threading library once the thread is started.

In retrospect, letting the listener classes be subclasses of threading.Thread was a poor choice, but one that probably cannot be undone until the next major version of this library. In the mean time, I have prepared a branch with a possible fix: fixup/win32-mouse-listener. Do you have any change of testing it out?

@therealadityashankar
Copy link

This doesn't work in macos either, this seems to be related to python 3.13 rather than windows

@therealadityashankar
Copy link

I tested fixup/win32-mouse-listener and that does not fix this in macos

@moses-palmer
Copy link
Owner

@therealadityashankar, the feature branch only contains fixes for win32.

I have prepared a new feature branch, fixup/listener-thread-handle that addresses this issue for all platforms. If you find the time, please try it!

@n-mou
Copy link
Author

n-mou commented Nov 21, 2024

Thanks for your attention. I'll try out this branch once I've figured our how to install it in a local environment (any help in that aspect woul de really appreciated).

@n-mou
Copy link
Author

n-mou commented Nov 21, 2024

Ok, I've managed to install it by running uv pip install "pynput @ ." at the repo main directory with the specified branch and it works (tested on python 3.13 in a virtual environment created by uv in the same conditions as those posted on the 1st comment on this issue):

Output:

2024-11-21 20:09:52,204: Mouse clicked at (4037, 1065) with Button.left
2024-11-21 20:09:52,732: Mouse clicked at (3268, 971) with Button.left
2024-11-21 20:09:53,228: Mouse clicked at (2810, 476) with Button.left
2024-11-21 20:09:54,231: Key.down
2024-11-21 20:09:54,376: Key.right
2024-11-21 20:09:54,510: Key.up
2024-11-21 20:09:54,662: Key.left
2024-11-21 20:09:54,744: Key.down
2024-11-21 20:09:55,942: Mouse clicked at (4636, 1143) with Button.left
2024-11-21 20:09:56,614: Key.ctrl_l
2024-11-21 20:09:56,798: '\x03'
2024-11-21 20:09:57,900: Mouse clicked at (4557, 1084) with Button.left
2024-11-21 20:09:58,686: Mouse clicked at (4545, 1103) with Button.left
2024-11-21 20:09:59,654: Key.ctrl_l
2024-11-21 20:10:00,014: '\x03'
2024-11-21 20:10:03,404: Mouse clicked at (4474, 1081) with Button.left
2024-11-21 20:10:03,620: Mouse clicked at (4475, 1069) with Button.left
2024-11-21 20:10:03,804: Mouse clicked at (4475, 1069) with Button.left
2024-11-21 20:10:04,388: Mouse clicked at (4410, 995) with Button.left
2024-11-21 20:10:05,726: Key.ctrl_l
2024-11-21 20:10:05,926: '\x03'
2024-11-21 20:10:06,640: 'q'
2024-11-21 20:10:06,798: 'q'
2024-11-21 20:14:54,310: Key.shift_r
2024-11-21 20:14:54,431: 'T'
2024-11-21 20:14:54,583: 'h'
2024-11-21 20:14:54,702: 'i'
2024-11-21 20:14:54,798: 's'
2024-11-21 20:14:54,950: Key.space
2024-11-21 20:14:55,094: 'i'
2024-11-21 20:14:55,214: 's'
2024-11-21 20:14:55,358: Key.space
2024-11-21 20:14:55,566: 'a'
2024-11-21 20:14:55,678: Key.space
2024-11-21 20:14:55,815: 't'
2024-11-21 20:14:55,950: 'e'
2024-11-21 20:14:56,135: 's'
2024-11-21 20:14:56,279: 't'
2024-11-21 20:14:56,895: Key.left
2024-11-21 20:14:56,982: Key.up
2024-11-21 20:14:57,134: Key.right
2024-11-21 20:14:57,238: Key.down
2024-11-21 20:14:57,326: Key.left
2024-11-21 20:14:57,446: Key.up
2024-11-21 20:14:57,534: Key.right
2024-11-21 20:14:57,640: Key.left
2024-11-21 20:14:57,879: Key.up
2024-11-21 20:14:57,881: Key.right
2024-11-21 20:14:57,882: Key.down
2024-11-21 20:14:58,024: Key.left
2024-11-21 20:14:58,494: Key.shift_r
2024-11-21 20:14:58,670: Key.shift_r
2024-11-21 20:14:58,815: Key.shift_r
2024-11-21 20:14:59,646: Key.shift_r
2024-11-21 20:14:59,766: '!'
2024-11-21 20:14:59,848: '"'
2024-11-21 20:14:59,950: '!'
2024-11-21 20:15:00,046: '"'
2024-11-21 20:15:00,270: Key.shift_r
2024-11-21 20:15:00,398: Key.shift_r
2024-11-21 20:15:01,290: Mouse clicked at (4415, 563) with Button.left
2024-11-21 20:15:01,674: Mouse clicked at (3846, 298) with Button.left
2024-11-21 20:15:02,170: Mouse clicked at (2901, 298) with Button.left
2024-11-21 20:15:02,634: Mouse clicked at (2778, 494) with Button.left
2024-11-21 20:15:03,162: Mouse clicked at (4349, 291) with Button.left
2024-11-21 20:15:05,238: Key.ctrl_l
2024-11-21 20:15:05,479: '\x03'
2024-11-21 20:15:06,222: 'q'
2024-11-21 20:15:07,819: Mouse clicked at (4391, 526) with Button.left
2024-11-21 20:15:08,078: 'q'
2024-11-21 20:15:10,072: Mouse clicked at (4317, 571) with Button.left
2024-11-21 20:15:10,390: 'q'
2024-11-21 20:20:32,350: Mouse clicked at (4531, 376) with Button.left
2024-11-21 20:20:32,645: Mouse clicked at (4531, 376) with Button.right
2024-11-21 20:20:34,238: Mouse clicked at (4580, 874) with Button.left
2024-11-21 20:20:34,988: Mouse clicked at (3348, 617) with Button.left
2024-11-21 20:20:35,268: Mouse clicked at (3338, 610) with Button.right
2024-11-21 20:20:35,774: Mouse clicked at (3287, 510) with Button.left
2024-11-21 20:20:36,316: Mouse clicked at (2974, 693) with Button.left
2024-11-21 20:20:36,918: Mouse clicked at (2988, 1081) with Button.left
2024-11-21 20:20:37,380: Mouse clicked at (4424, 983) with Button.left
2024-11-21 20:20:38,263: 's'
2024-11-21 20:20:38,303: 'd'
2024-11-21 20:20:38,438: 'w'
2024-11-21 20:20:38,440: 'p'
2024-11-21 20:20:38,454: 'e'
2024-11-21 20:20:38,545: 'f'
2024-11-21 20:20:38,568: 'j'
2024-11-21 20:20:38,638: 'w'
2024-11-21 20:20:38,655: 'e'
2024-11-21 20:20:38,743: 'f'
2024-11-21 20:20:38,768: 'j'
2024-11-21 20:20:38,769: 'o'
2024-11-21 20:20:38,854: 'w'
2024-11-21 20:20:38,855: 'p'
2024-11-21 20:20:38,878: 'e'
2024-11-21 20:20:38,880: 'o'
2024-11-21 20:20:38,935: 'f'
2024-11-21 20:20:38,959: 'j'
2024-11-21 20:20:39,050: 'e'
2024-11-21 20:20:39,070: 'r'
2024-11-21 20:20:39,072: 'p'
2024-11-21 20:20:39,087: 'i'
2024-11-21 20:20:39,142: 'h'
2024-11-21 20:20:39,206: 'w'
2024-11-21 20:20:39,294: 'g'
2024-11-21 20:20:39,336: 'w'
2024-11-21 20:20:39,336: 'p'
2024-11-21 20:20:39,422: 'r'
2024-11-21 20:20:39,473: 'f'
2024-11-21 20:20:39,473: 'j'
2024-11-21 20:20:40,582: Key.ctrl_l
2024-11-21 20:20:40,806: '\x03'
2024-11-21 20:20:41,702: Key.ctrl_l
2024-11-21 20:20:41,950: '\x03'
2024-11-21 20:20:42,454: 'q'
2024-11-21 20:20:42,606: 'q'
2024-11-21 20:21:11,764: Mouse clicked at (3046, 673) with Button.left
2024-11-21 20:21:12,020: Mouse clicked at (3046, 673) with Button.right
2024-11-21 20:21:12,564: Mouse clicked at (3055, 589) with Button.left
2024-11-21 20:21:13,100: Mouse clicked at (3014, 519) with Button.right
2024-11-21 20:21:13,804: Mouse clicked at (1811, 1218) with Button.left
2024-11-21 20:21:14,204: Mouse clicked at (1811, 1218) with Button.right
2024-11-21 20:21:14,932: Mouse clicked at (4093, 1025) with Button.left
2024-11-21 20:21:15,942: 'w'
2024-11-21 20:21:15,974: 'r'
2024-11-21 20:21:16,046: 'p'
2024-11-21 20:21:16,110: 'i'
2024-11-21 20:21:16,134: 'w'
2024-11-21 20:21:16,150: 'e'
2024-11-21 20:21:16,151: 'q'
2024-11-21 20:21:16,241: 'f'
2024-11-21 20:21:16,310: 'p'
2024-11-21 20:21:16,326: 'i'
2024-11-21 20:21:16,398: 'h'
2024-11-21 20:21:16,455: 'w'
2024-11-21 20:21:16,486: 'p'
2024-11-21 20:21:16,510: 'i'
2024-11-21 20:21:16,551: 'g'
2024-11-21 20:21:16,590: 'b'
2024-11-21 20:21:16,686: 'p'
2024-11-21 20:21:16,726: 'e'
2024-11-21 20:21:16,774: 'i'
2024-11-21 20:21:16,798: 'g'
2024-11-21 20:21:16,800: 'b'
2024-11-21 20:21:17,462: Key.up
2024-11-21 20:21:17,502: Key.left
2024-11-21 20:21:17,686: Key.right
2024-11-21 20:21:17,838: Key.down
2024-11-21 20:21:17,926: Key.left
2024-11-21 20:21:18,112: Key.up
2024-11-21 20:21:18,114: Key.right
2024-11-21 20:21:18,270: Key.left
2024-11-21 20:21:18,360: Key.down
2024-11-21 20:21:19,086: Key.shift_r
2024-11-21 20:21:19,246: '!'
2024-11-21 20:21:19,311: '"'
2024-11-21 20:21:19,366: '�'
2024-11-21 20:21:19,479: '"'
2024-11-21 20:21:19,480: '!'
2024-11-21 20:21:19,584: '�'
2024-11-21 20:21:19,702: '!'
2024-11-21 20:21:19,806: '�'
2024-11-21 20:21:21,879: Key.alt_l
2024-11-21 20:21:22,104: 'q'
2024-11-21 20:21:22,126: 'w'
2024-11-21 20:21:22,214: 'd'
2024-11-21 20:21:22,313: 'q'
2024-11-21 20:21:22,334: 'w'
2024-11-21 20:21:22,438: 'd'
2024-11-21 20:21:22,502: 'q'
2024-11-21 20:21:22,726: '2'
2024-11-21 20:21:22,729: '1'
2024-11-21 20:21:22,854: '3'
2024-11-21 20:21:22,943: '2'
2024-11-21 20:21:22,945: '1'
2024-11-21 20:21:23,047: '3'
2024-11-21 20:21:23,150: '1'
2024-11-21 20:21:23,190: '2'
2024-11-21 20:21:23,254: '3'
2024-11-21 20:21:24,254: Key.ctrl_l
2024-11-21 20:21:24,718: '\x03'
2024-11-21 20:21:25,647: '\x03'
2024-11-21 20:21:25,894: '\x03'

Also, I think this is a flaw with the snippet I've posted but when a keyboard exception is raised (pressing Ctrl+C) the program doesn't stop, but when I stop the program by pressing the Escape key, the unhandled exception is printed to stderr (as if the listener prevented the stderr output from updating and when calling sys.exit() the output stream suddenly was updated)

  File "C:\Users\User\Dev\pynput_test\pynput\app.py", line 30, in <module>
    listener.join()
    ~~~~~~~~~~~~~^^
  File "C:\Users\User\Dev\pynput_test\pynput\.venv\Lib\site-packages\pynput\_util\__init__.py", line 271, in join
    super(AbstractListener, self).join(timeout, *args)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^
  File "C:\Users\Master\AppData\Roaming\uv\python\cpython-3.13.0-windows-x86_64-none\Lib\threading.py", line 1092, in join
    self._handle.join(timeout)
    ~~~~~~~~~~~~~~~~~^^^^^^^^^
KeyboardInterrupt

I've solved by surrounding the listener.join() with a try/catch block. But maybe there's a more idiomatic way of doing it. Also, is there a way to setup the keyboard listener to stop when a KeyboardInterrupt exception is raised so I don't need to code edge cases in the on_press method?

@therealadityashankar
Copy link

@moses-palmer I tested this out on macos, and it still does not work, sorry!

I used the following script to test this out

from pynput import keyboard

def on_press(key):
    try:
        print(f"Key pressed: {key.char}")
    except AttributeError:
        # Special keys (e.g., arrow keys, function keys)
        print(f"Special key pressed: {key}")

def on_release(key):
    print(f"Key released: {key}")
    if key == keyboard.Key.esc:
        # Stop listener when 'Esc' key is released
        print("Escape key released, exiting...")
        return False

# Start the listener
with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
    print("Key logger is running. Press 'Esc' to stop.")
    listener.join()

I get the following error upon a key press

Key logger is running. Press 'Esc' to stop.
Unhandled exception in listener callback
Traceback (most recent call last):
  File "/Users/riversnow/Desktop/job-automation/venv/lib/python3.13/site-packages/pynput/_util/__init__.py", line 229, in inner
    return f(self, *args, **kwargs)
  File "/Users/riversnow/Desktop/job-automation/venv/lib/python3.13/site-packages/pynput/_util/darwin.py", line 283, in _handler
    self._handle(proxy, event_type, event, refcon)
    ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: '_thread._ThreadHandle' object is not callable

@FujiwaraChoki
Copy link

I'm getting the same issue.

@FujiwaraChoki
Copy link

FujiwaraChoki commented Nov 26, 2024

I found the issue, simply downgrade Python to 3.11.6.

For UV:

uv venv --python 3.11.6

@therealadityashanka

@therealadityashankar
Copy link

Hi there @FujiwaraChoki 👋🏽 ,
That was the first comment I had made :)

@FujiwaraChoki
Copy link

Hi there @FujiwaraChoki 👋🏽 , That was the first comment I had made :)

Oh sorry lol. Glad you found the issue!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants