-
Notifications
You must be signed in to change notification settings - Fork 251
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
MacOS crash when starting pynput keyboard listener after qt6 #511
Comments
FYI: this happens with tkinter and pyqt6, too: tkinter: from tkinter import *
from pynput import keyboard
class MyListener():
def __init__(self):
def on_press(key):
print("You pressed {0}".format(key))
def on_release(key):
print("You released {0}".format(key))
self.listener = keyboard.Listener(
on_press=on_press,
on_release=on_release)
def start(self):
self.listener.start()
self.listener.wait()
print("listener has started? {0}".format(self.listener.running))
listener = MyListener()
root = Tk() # create parent window
def start_pynput():
print("beep")
listener.start()
print("boop")
# use Button and Label widgets to create a simple TV remote
button = Button(root, text="Start Pynput", command=start_pynput)
button.pack()
root.mainloop() pyqt6 import sys
from PyQt6 import (
QtWidgets,
)
from pynput import keyboard
class MyListener():
def __init__(self, label: QtWidgets.QLabel):
def on_press(key):
label.setText("You pressed {0}".format(key))
def on_release(key):
label.setText("You released {0}".format(key))
self.listener = keyboard.Listener(
on_press=on_press,
on_release=on_release)
def start(self):
self.listener.start()
self.listener.wait()
print("listener has started? {0}".format(self.listener.running))
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Listener Demo 2")
central_widget = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout()
central_widget.setLayout(layout)
label_description = QtWidgets.QLabel("Press the button to crash")
layout.addWidget(label_description)
label = QtWidgets.QLabel("Press any key")
label.setEnabled(False)
layout.addWidget(label)
button = QtWidgets.QPushButton("Start listener!")
button.pressed.connect(self.start_listener)
layout.addWidget(button)
self.listener = MyListener(label)
self.setCentralWidget(central_widget)
def start_listener(self):
print("beep")
self.listener.start()
print("boop")
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec() |
Same here, Error message: working environment:
here's the code # -*- coding: utf-8 -*-
import random
import string
import time
import pyperclip
from pynput import keyboard
from PySide6 import QtCore
from PySide6 import QtWidgets
class Main(QtWidgets.QMainWindow):
signal = QtCore.Signal()
def __init__(self):
super().__init__()
def build(self):
self.signal.connect(self.get_text_from_clip)
self.button = QtWidgets.QPushButton()
self.button.clicked.connect(self.button_pressed)
self.keyboard_detect_start()
self.setCentralWidget(self.button)
self.show()
def keyboard_detect_start(self, key="<ctrl>+q"):
def for_canonical(hotkey_event):
return lambda key: hotkey_event(self.listener.canonical(key))
hotkey = keyboard.HotKey(keyboard.HotKey.parse(key), self.signal.emit)
self.listener = keyboard.Listener(
on_press=for_canonical(hotkey.press),
on_release=for_canonical(hotkey.release),
)
self.listener.start()
def get_text_from_clip(self):
controller = keyboard.Controller()
controller.press(keyboard.Key.cmd)
controller.press("c")
controller.release("c")
controller.release(keyboard.Key.cmd)
time.sleep(0.05)
print(pyperclip.paste().strip())
def button_pressed(self):
self.listener.stop()
self.listener.join()
time.sleep(0.5)
new_key = random.choices(string.ascii_lowercase)[0]
print("new_key: ", new_key)
self.keyboard_detect_start(key=f"<ctrl>+{new_key}")
if __name__ == "__main__":
app = QtWidgets.QApplication([])
main = Main()
main.build()
app.exec() |
Yes, #512 does fix this for me. [Edited] 2022/11/22 So far I know is that the But if I simply change the way of invoking
# -*- coding: utf-8 -*-
import time
import platform
import pyperclip
from pynput import keyboard
from PySide6 import QtCore
from PySide6 import QtWidgets
class Worker(QtCore.QObject):
def __init__(self):
super().__init__()
def run_method(self):
activate_key = "<ctrl>+q"
def for_canonical(hotkey_event):
return lambda key: hotkey_event(self.listener.canonical(key))
hotkey = keyboard.HotKey(keyboard.HotKey.parse(activate_key), self.print_text_from_clipboard)
self.listener = keyboard.Listener(
on_press=for_canonical(hotkey.press),
on_release=for_canonical(hotkey.release),
)
self.listener.start()
def print_text_from_clipboard(self):
# delay is needed before getting str from clip
if platform.system() == "Windows":
modifier = keyboard.Key.ctrl
elif platform.system() == "Darwin":
modifier = keyboard.Key.cmd
controller = keyboard.Controller()
controller.press(modifier)
controller.press("c")
controller.release("c")
controller.release(modifier)
time.sleep(0.05)
print("text: ", pyperclip.paste().strip())
class Main(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
def build(self):
self.worker = Worker()
self.button = QtWidgets.QPushButton()
self.button.clicked.connect(self.button_pressed)
self.setCentralWidget(self.button)
self.show()
def button_pressed(self):
self.worker.run_method()
if __name__ == "__main__":
app = QtWidgets.QApplication([])
main = Main()
main.build()
app.exec()
# -*- coding: utf-8 -*-
import time
import platform
import pyperclip
from pynput import keyboard
from PySide6 import QtCore
from PySide6 import QtWidgets
class Worker(QtCore.QObject):
signal = QtCore.Signal()
def __init__(self):
super().__init__()
def run_method(self):
activate_key = "<ctrl>+q"
def for_canonical(hotkey_event):
return lambda key: hotkey_event(self.listener.canonical(key))
hotkey = keyboard.HotKey(keyboard.HotKey.parse(activate_key), self.signal.emit)
self.listener = keyboard.Listener(
on_press=for_canonical(hotkey.press),
on_release=for_canonical(hotkey.release),
)
self.listener.start()
def print_text_from_clipboard(self):
# delay is needed before getting str from clip
if platform.system() == "Windows":
modifier = keyboard.Key.ctrl
elif platform.system() == "Darwin":
modifier = keyboard.Key.cmd
controller = keyboard.Controller()
controller.press(modifier)
controller.press("c")
controller.release("c")
controller.release(modifier)
time.sleep(0.05)
print("text: ", pyperclip.paste().strip())
class Main(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
def build(self):
self.worker = Worker()
self.worker.signal.connect(self.worker.print_text_from_clipboard)
self.button = QtWidgets.QPushButton()
self.button.clicked.connect(self.button_pressed)
self.setCentralWidget(self.button)
self.show()
def button_pressed(self):
self.worker.run_method()
if __name__ == "__main__":
app = QtWidgets.QApplication([])
main = Main()
main.build()
app.exec() |
Just found something interesting. Without applying changes in #512, the following code works. It reminds me that Does this code work for you? @AlvaroMunoz # -*- coding: utf-8 -*-
from pynput import keyboard
from PySide6 import QtWidgets
class Main(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
def build(self):
def for_canonical(hotkey_event):
return lambda key: hotkey_event(self.listener.canonical(key))
hotkey = keyboard.HotKey(keyboard.HotKey.parse("<ctrl>+q"), lambda: print("keyboard detected"))
self.listener = keyboard.Listener(
on_press=for_canonical(hotkey.press),
on_release=for_canonical(hotkey.release),
)
self.listener.start()
self.show()
if __name__ == "__main__":
app = QtWidgets.QApplication([])
main = Main()
main.build()
app.exec() |
Same issue, MacBook Air M2 on MacOs Sonoma 14.0 Beta |
Description
If I create and start a listener AFTER launching a qt6 app (pyside6), the application crashes.
Platform and pynput version
macOS Monterey (12.6), M1 Pro. Pynput 1.7.6, Pyside6 6.4.0, Python 3.10. I'm also using a Latin American keyboard layout.
To Reproduce
https://github.com/alvaromunoz/pynput-macos-issues/blob/ba17e4b83f1eb239454d73ba96adf7f5fe71673b/nested_crash.py
OUTPUT:
The text was updated successfully, but these errors were encountered: