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

I can't use pynput in MacOS Monterey 12.0.1 + M1 environment #424

Open
yejunxi opened this issue Nov 29, 2021 · 12 comments
Open

I can't use pynput in MacOS Monterey 12.0.1 + M1 environment #424

yejunxi opened this issue Nov 29, 2021 · 12 comments
Labels

Comments

@yejunxi
Copy link

yejunxi commented Nov 29, 2021

Description
Hello, I want to ask for help, I can't use pynput in MacOS Monterey 12.0.1 + M1 environment

 File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "/Users/yjx/Documents/my/xueqiu2/venv/lib/python3.8/site-packages/pynput/_util/darwin.py", line 130, in keycode_context
    layout = _wrap_value(CarbonExtra.TISGetInputSourceProperty(
  File "/Users/yjx/Documents/my/xueqiu2/venv/lib/python3.8/site-packages/pynput/_util/darwin.py", line 45, in _wrap_value
    return objc.objc_object(c_void_p=value)
AttributeError: 'NoneType' object has no attribute 'value'
Exception in thread Thread-6:
Traceback (most recent call last):
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/Users/yjx/Documents/my/xueqiu2/venv/lib/python3.8/site-packages/pynput/_util/__init__.py", line 193, in run
    self._run()
  File "/Users/yjx/Documents/my/xueqiu2/venv/lib/python3.8/site-packages/pynput/keyboard/_darwin.py", line 250, in _run
    with keycode_context() as context:
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "/Users/yjx/Documents/my/xueqiu2/venv/lib/python3.8/site-packages/pynput/_util/darwin.py", line 130, in keycode_context
    layout = _wrap_value(CarbonExtra.TISGetInputSourceProperty(
  File "/Users/yjx/Documents/my/xueqiu2/venv/lib/python3.8/site-packages/pynput/_util/darwin.py", line 45, in _wrap_value
    return objc.objc_object(c_void_p=value)
AttributeError: 'NoneType' object has no attribute 'value'

Platform and pynput version
System:macOS Monterey 12.0.1 + M1
pynput 1.7.5
python 3.8

To Reproduce
Use official examples

#!venv/bin/python3

import os

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()
os.system('echo "Press any key to continue..." && read')
@yejunxi
Copy link
Author

yejunxi commented Nov 30, 2021

I made a temporary solution, but I hope the author can help to see why

drawin.py

def _wrap_value(value):
    """Converts a pointer to a *Python objc* value.

    :param value: The pointer to convert.

    :return: a wrapped value
    """
    if value is None:
        return
    return objc.objc_object(c_void_p=value)

@moses-palmer
Copy link
Owner

Thank you for your report and proposed fix.

I think your proposition is the way to go; previously this library used a function loaded by ctypes, and I presume it just silently returned None when passed None, whereas the new managed method presumably checks its arguments.

I have included your fix in the branch fixup-macos-objc-none. If you should find time, please test it; otherwise, I will merge it eventually.

@tevenfeng
Copy link

tevenfeng commented Dec 30, 2021

Thank you for your report and proposed fix.

I think your proposition is the way to go; previously this library used a function loaded by ctypes, and I presume it just silently returned None when passed None, whereas the new managed method presumably checks its arguments.

I have included your fix in the branch fixup-macos-objc-none. If you should find time, please test it; otherwise, I will merge it eventually.

I've tested this branch on my M1 mbp with Big Sur, no errors like before. Maybe you could merge it now.

@g0t4
Copy link

g0t4 commented Oct 7, 2022

I'm having similar issues with my M1 mac running macOS Ventura but only when I use pynput with Qt... seems to fail similarly to the above issue with TISGetInputSourceProperty crashing my app.

I have rearranged Qt / pynput startup order and encountered some lazy load race conditions / timing issues with pyobjc behind the scenes such that I can get both to work in simple setups but I have another setup where I'm getting the following trace and haven't had much luck finding out why... I'll keep plugging away on it and share what I find.

All of the issues I've had (race conditions, and the following) stem from the same spot (or nearby) with regards to the keycode_context creation and involve Carbon API calls.

  ffi_call_SYSV (in libffi.dylib) + 80
  TSMGetInputSourceProperty (in HIToolbox) + 44
  isValidateInputSourceRef (in HIToolbox) + 92
  islGetInputSourceListWithAdditions (in HIToolbox) + 160
  _dispatch_assert_queue_fail (in libdispatch.dylib) + 0
  0xffff80018b7f991c
  _sigtramp (in libsystem_platform.dylib) + 56

@g0t4
Copy link

g0t4 commented Oct 7, 2022

I also ran into a crash when TSMCurrentAsciiCapableKeyboardLayoutInputSourceRefCreate was invoked (if I bypass the call to TISGetInputSourceProperty... so I commented out both calls and key logging worked... :)

@perroboc
Copy link

perroboc commented Oct 21, 2022

In my case, I'm also using a QT as a frontend. I'm creating a Controller at the start, and a Listener on demand. My app crashes when starting the Listener.

I've modified _wrap_value in _util/darwin.py to log some info:

def _wrap_value(value):
    """Converts a pointer to a *Python objc* value.

    :param value: The pointer to convert.

    :return: a wrapped value
    """
    print(f"Called _wrap_value({value})")
    object = objc.objc_object(c_void_p=value) if value is not None else None
    print(f"Called _wrap_value({value}) = {object}")
    return object

When loading Controller at the start, I get this:

Called _wrap_value(4649539536)
Called _wrap_value(4649539536) = <TSMInputSource 0x1152257d0> KB Layout: Latin American (id=89)
Called _wrap_value(5195413504)
Called _wrap_value(5195413504) = b'\x02\x10\x00\x01\x00\x03\x00\x00\x1b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x03\x00\x00<\x1c\x00\x00P"\x00\x00\...

And then, when starting the listener:

Called _wrap_value(4649539536)

And then it crashes. Maybe it has something to do with the pointer being reused?

EDIT: Turned off the Controller, and the Listener keeps crashing the app :(

@g0t4
Copy link

g0t4 commented Oct 21, 2022 via email

@perroboc
Copy link

It’s an issue with pyobjc and how it registers/resolves arg types and results try adding this when your script/program starts up (before invoking pynput) and see if the issue resolves: import objc import CoreFoundation objc.registerCFSignature("CFStringRef", b"^{__CFString=}", CoreFoundation.CFStringGetTypeID(), "NSString")

Sadly, no, it keeps crashing only when Listener.start/join is called, even if Controller is not started, but my bug seems to be a new one...

... Something to do with the thread it's running in. The Controller is called on the main thread, while the listener in its own new thread. If I start the Controller and the Listener in the same object the application doesn't crash.

This MUST be a bug with objc way of creating objects from pointers. This line is the culprit:

return objc.objc_object(c_void_p=value) if value is not None else None

When invoking that line on creating a Listener from a new thread, on MacOS Monterey Apple Silicon, it crashes. The same software on Windows runs fine.

@perroboc
Copy link

So @g0t4 is right on this one. If I start the pynput keyboard Listener before QT, it works. But if I start it after QT, it fails and crashes the app.

Amund211 added a commit to Amund211/prism that referenced this issue May 29, 2023
@Amund211
Copy link
Contributor

I'm having similar issues with my M1 mac running macOS Ventura but only when I use pynput with Qt... seems to fail similarly to the above issue with TISGetInputSourceProperty crashing my app.

I have rearranged Qt / pynput startup order and encountered some lazy load race conditions / timing issues with pyobjc behind the scenes such that I can get both to work in simple setups but I have another setup where I'm getting the following trace and haven't had much luck finding out why... I'll keep plugging away on it and share what I find.

All of the issues I've had (race conditions, and the following) stem from the same spot (or nearby) with regards to the keycode_context creation and involve Carbon API calls.

  ffi_call_SYSV (in libffi.dylib) + 80
  TSMGetInputSourceProperty (in HIToolbox) + 44
  isValidateInputSourceRef (in HIToolbox) + 92
  islGetInputSourceListWithAdditions (in HIToolbox) + 160
  _dispatch_assert_queue_fail (in libdispatch.dylib) + 0
  0xffff80018b7f991c
  _sigtramp (in libsystem_platform.dylib) + 56

@g0t4 Hi!

I'm having an issue with all the same symptoms as this, only using tkinter instead. Your proposed fix does not seem to work for me either.

Is there an issue we can file with pyobjc or do you know of an existing one to track the progress of this? It's impractical in my case to start the listener before I start tkinter.

Thank you.

@Raymo111
Copy link

Also impractical for me, and this is enough of a blocker that I'll have to switch away to another library. @moses-palmer can we reopen this issue for more visibility please?

@moses-palmer
Copy link
Owner

@Raymo111, sure, I'll reopen.

@moses-palmer moses-palmer reopened this May 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants