moses-palmer / pynput

Sends virtual input commands
GNU Lesser General Public License v3.0
1.79k stars 248 forks source link

pynput doesn't properly join or kill listeners inside a python virtual enviorment #434

Open rydb opened 2 years ago

rydb commented 2 years ago

Description Im trying to use mouse and keyboard listener inside a python virtual environment, and both listener's behavior is glitchy. It appears neither thread is joined when the .join() function is called, and although both threads can be killed separately with .stop(), control is not returned to the main thread, what ever program attempts to run those threads can't continue.

Platform and pynput version Ubuntu 20.04 and pynput 1.7.5

To Reproduce Create a fresh virtual enviorment and source it python3 -m venv test_venv source test_venv/bin/activate

install pynput in venv pip3 install pynput

run the below code:

from pynput.keyboard import Listener as KeyboardListener
from pynput.mouse import Listener as MouseListener

def listen_start():    
    keyboard_listener.start()
    mouse_listener.start()
    keyboard_listener.join()
    mouse_listener.join()
    print("both threads killed")

#Stop listening for keyboard presses/mouse presses
def listen_stop():
    print("THE THREAD STOPPED")

    mouse_listener.stop()
    keyboard_listener.stop()

def _on_press( input_key):
    print("press!")
    listen_stop()

def _on_release(input_key):    
    pass
def _on_click( mouse_x, mouse_y, button, click):
    print('click!')
    listen_stop()

keyboard_listener = KeyboardListener(on_press=_on_press, on_release=_on_release)
mouse_listener = MouseListener(on_click=_on_click)

listen_start()

"THE THREAD STOPPED" should only run once, but it runs twice, meaning .join() isn't functional, and .stop() does resume control for the main non listener threads, so the program is stuck.

This code, however, does run as expected outside of a virtual environment.

moses-palmer commented 2 years ago

Thank you for your report.

I think the issue might be with a recent regression in pynput rather than something related to virtual environments. Are you certain that the version in use outside of the virtual environment is the same as the one inside?

I have pushed a fix to the master branch that I think will fix your issue---using it, the script you provided above does terminate as expected. Is is possible for you to test?

edraft commented 2 years ago

Try updating to 1.7.6 Fixed it for me

rydb commented 2 years ago

Thank you for your report.

I think the issue might be with a recent regression in pynput rather than something related to virtual environments. Are you certain that the version in use outside of the virtual environment is the same as the one inside?

I have pushed a fix to the master branch that I think will fix your issue---using it, the script you provided above does terminate as expected. Is is possible for you to test?

The threads still do not properly close inside a virtual machine in 1.7.6, I added listen_start() to the end of the sample code, and closing the threads require BOTH a mouse click and keyboard press to close. Outside of a virtual machine, its only a keyboard press or mouse click.

rydb commented 2 years ago

Try updating to 1.7.6 Fixed it for me

any sample code to look at?