Stop mouse event when pressing key - python-3.x

My code uses mouse events to send messages but I have no idea how to stop using an f1 key. I didn't find a stop () method as in Listener () in Events ().
import pynput
import pyautogui
import time
from pynput import mouse
from pynput import keyboard
running = True
mouse_event = mouse.Events()
def on_press(key):
global running
if key == keyboard.Key.f1:
running = False
print('end')
return False
def msg():
mouse_event.start()
for event in mouse_event:
if running:
if isinstance(event,mouse.Events.Click):
if not event.pressed:
pyautogui.typewrite('hello world\n',interval=0.009)
else:
time.sleep(1)
return False
while 1:
print("Choose the desired option")
print("1. Message")
option = int(input("Option:"))
if option == 1:
running = True
with keyboard.Listener(on_press=on_press) as listener:
if running:
msg()
elif not listener.running:
time.sleep(2)
break
Is there a way to interrupt a mouse event with the press of a key?
One attempt was to pass the method as on_press to Events () does not work.

I've had to do something similar in the past and I ended up using threading to have one thread listen for the mouse/keyboard input while the other runs my main program.
import time
from pynput import keyboard
from threading import Thread
def exit_program():
def on_press(key):
if str(key) == 'Key.f1':
main.status = 'pause'
user_input = input('Program paused, would you like to continue? (y/n) ')
while user_input != 'y' and user_input != 'n':
user_input = input('Incorrect input, try either "y" or "n" ')
if user_input == 'y':
main.status = 'run'
elif user_input == 'n':
main.status = 'exit'
exit()
with keyboard.Listener(on_press=on_press) as listener:
listener.join()
def main():
main.status = 'run'
while True:
print('running')
time.sleep(1)
while main.status == 'pause':
time.sleep(1)
if main.status == 'exit':
print('Main program closing')
break
Thread(target=main).start()
Thread(target=exit_program).start()

Related

exit loop pynput thread

Hello i'm trying to make a program to play snake using pynput.
When I press space the program runs but even if I press backspace i can't stop it, I know that I have to use threading but I don't figure how it works, thank you
my code :
from pynput import keyboard
from pynput.keyboard import Key, Controller
import threading
import time
kb = Controller()
def droite(key):
kb.press(Key.right)
kb.release(Key.right)
def gauche(key):
kb.press(Key.left)
kb.release(Key.left)
def haut(key):
kb.press(Key.up)
kb.release(Key.up)
def bas(key):
kb.press(Key.down)
kb.release(Key.down)
def on_press(key):
if key == Key.space:
print('yes')
droite(Key.right)
time.sleep(1.7)
haut(Key.up)
time.sleep(0.9)
gauche(Key.left)
time.sleep(2.15)
bas(Key.down)
time.sleep(1.9)
droite(Key.right)
time.sleep(2.15)
for i in range(255):
for i in range(6):
haut(Key.up)
time.sleep(0.1 )
gauche(Key.left)
time.sleep(2.1)
haut(Key.up)
time.sleep(0.1)
droite(Key.right)
time.sleep(2.1)
gauche(Key.left)
time.sleep(2.15)
bas(Key.down)
time.sleep(1.9)
droite(Key.right)
def on_release(key):
if key == Key.backspace:
print('no')
KeyboardInterrupt
return False
with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
listener.join()
th1 = threading.Thread(target=on_press)
th1.start()
th2 = threading.Thread(target=on_release)
th2.start()
th1.join()
th2.join()
I'm trying to stop the program even if I'm in a loop when I press a key

How to break countdown with keyboard in python3?

In the middle of some process I have a pause with countdown (for loop with time.sleep(1) inside). I'd like to be able to break it with keyboard to be able to continue earlier than countdown got finished.
Is it possible with python3 (cross-platform without Linux root access)? Can I get some information about key pressed in this case ?
Related to this question: Use getch in while (1) python
Solution: use kbhit() and getch(): https://docs.python.org/3.10/library/msvcrt.html#console-i-o
Working example:
import msvcrt
from time import sleep
def a():
for n in range(10):
if msvcrt.kbhit():
return msvcrt.getch()
sleep(1)
Note that it has a reaction delay of up to 1 second
Here is my "cross-platform" very simplified solution.
def my_sleep(wait_sec):
current_platform = platform.system()
if current_platform == "Windows":
import msvcrt
elif current_platform == "Linux":
import termios
from select import select
# save the terminal settings
fd = sys.stdin.fileno()
new_term = termios.tcgetattr(fd)
old_term = termios.tcgetattr(fd)
# switch to normal terminal
def set_normal_term():
termios.tcsetattr(fd, termios.TCSAFLUSH, old_term)
# switch to unbuffered terminal
def set_curses_term():
termios.tcsetattr(fd, termios.TCSAFLUSH, new_term)
def kbhit():
dr, dw, de = select([sys.stdin], [], [], 0)
return dr != []
set_curses_term()
# new terminal setting unbuffered
new_term[3] = (new_term[3] & ~termios.ICANON & ~termios.ECHO)
set_curses_term()
for sec_left in range(wait_sec, 0, -1):
if current_platform == 'Windows':
if msvcrt.kbhit():
# print(f':: {msvcrt.getch()}')
break
elif current_platform == 'Linux':
if kbhit():
ch = sys.stdin.read(1)
# print(f':: {ch}')
break
print(sec_left)
time.sleep(1)
if current_platform == "Linux":
set_normal_term()

How to run time.sleep() without stopping while loop

Is there a way to call a function which has wait(time.sleep()) from infinite while loop without disturbing the loop?
I am trying to run a few task that require to wait for a few seconds but the issue is that the while loop also stops when the wait process is happening.
This is what I have tried out-
Here is my code:
import cv2
import time
def waiting():
print("Inside function")
# Running Some Tasks
time.sleep(5)
print("Done sleeping")
def main():
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
cv2.imshow("Webcam", frame)
k = cv2.waitKey(10)
if k == 32: # Press SPACEBAR for wait function
waiting()
elif k == 27: # Press ESC to stop code
break
cap.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
main()
Thanks for the quick responses from #JLT and #TerePiim. Here is the updated code for anyone who might benefit from this:
import cv2
import time
import threading
def waiting():
print("Inside parallel function")
# Running some Tasks
time.sleep(5)
print("Done sleeping")
def main():
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
cv2.imshow("Webcam", frame)
k = cv2.waitKey(10)
if k == 32: # Press SPACEBAR for wait function
t = threading.Thread(target=waiting)
t.start()
elif k == 27: # Press ESC to stop code
break
cap.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
main()
You are working in a single thread script at the moment. You should use threading or multiprocessing. This makes (it look like) multiple processes (are) active. Dependent on if you use threading or multiprocessing.
You should use threads. It will look like the computer is doing them both at the same time.
import threading
t = threading.Thread(target=function)
t.start()

Multi - threading click macro / click recorder

I am working on a script that will listen to keystrokes till the 'q' button is pressed, afterwards it should stop the script and print out the mouse positions that were saved in 2 seconds intervals. I can't manage the threads and I am still learning this topic. Each time I run the code nothing happens but the process is running:
from pynput.keyboard import Listener
import pyautogui
from multiprocessing import Process
import time
mouse_positions = []
def func1():
while True:
time.sleep(2)
mouse_positions.append(pyautogui.position())
cordinates = []
quit_status = False
keystrokes = []
def on_press(key):
if "q" in str(key) :
print('q was pressed!')
exit("Stopped running")
#qprint(key)
keystrokes.append(key)
print(keystrokes)
#print(keystrokes)
if __name__ == '__main__':
p1 = Process(target=func1)
p1.start()
p1.join()
with Listener(on_press=on_press) as listener: # Create an instance of Listener
listener.join() # Join the listener thread to the main thread to keep waiting for keys
EDIT :
To anyone intrested, here is a click macro I built, script I built previously was more like mouse capture movement. The script below will record your mouse clicks and afterwards will replay them. Much better.
from pynput.keyboard import Listener
import pyautogui
from pynput import mouse
import time
x_pos = []
y_pos = []
both_pos = []
pressed_key = None
def on_click(x, y, button, pressed):
if pressed:
#print ("{0} {1}".format(x,y))
print(pressed_key)
if pressed_key == "1":
both_pos.append("{0}".format(x,y))
both_pos.append("{1}".format(x,y))
#print("test" + x_pos + y_pos)
print (x_pos + y_pos)
else:
pass
if pressed_key == 'q':
return False
def on_press(key):
print("To replay press 'q' , to stop recording press '1' , to record again press '1' .")
global pressed_key
if 'Key.esc' in str(key):
return False
if '1' in str(key):
pressed_key= None if pressed_key == '1' else '1'
if 'q' in str(key):
print("Replaying actions")
print(str(len(both_pos)))
for point in range(0,len(both_pos),2):
time.sleep(3)
print("clicking")
pyautogui.click(x=int(both_pos[point]),y=int(both_pos[point+1]))
print("done...")
return False
mouse_listener = mouse.Listener(on_click=on_click)
mouse_listener.start()
with Listener(on_press=on_press) as listener: # Create an instance of Listener
listener.join()
#print(mouse_listener.mouse_positions)
Hi you can use threading module.
I have created class MouseListener which inherit from threading.Thread class. Everything what you want to run put into run method. As thread stopper I used still_run attribute.
When you are typing, I pass to on_press function pressed key and mouse_listener. If q is pressed I set mouse_listener.still_run to False, what leads to stop the mouse listener.
mouse_positions I moved from global scope to MouseListener.
import threading
from pynput.keyboard import Listener
import pyautogui
import time
class MouseListener(threading.Thread):
still_run = True
mouse_positions = []
def run(self):
self.func()
def func(self):
while self.still_run:
time.sleep(2)
self.mouse_positions.append(pyautogui.position())
print(self.mouse_positions)
coordinates = []
quit_status = False
keystrokes = []
def on_press(key, mouse_listener):
print('kp')
if "q" in str(key):
print('q was pressed!')
mouse_listener.still_run = False
print(key)
exit("Stopped running")
keystrokes.append(key)
print(keystrokes)
print(keystrokes)
if __name__ == '__main__':
mouse_listener = MouseListener()
mouse_listener.start()
with Listener(on_press=lambda key: on_press(key, mouse_listener)) as listener: # Create an instance of Listener
listener.join()
print(mouse_listener.mouse_positions)

Keyboard module to return true or false statements

I am currently utilizing the pypi keyboard module and trying to return a statement of true when pressing a key while the key is pressed (e.g. "up" key), and then return false while the key is not pressed. I can initially get the program to print true or false with loops, only problem is I have to break after true or suffer infinite loop prints of true.
I would like for the program not break unless I hit the esc key.
import keyboard
x = keyboard.read_key()
while True:
try:
if x == "up":
print("True")
elif x != "up":
print("False")
except:
keyboard.wait("esc")
I was able to figure this out and I feel silly, I just wanted to ask the question to get the thought process going.
I ended up with:
import keyboard
import time
bulb = False
def LightSwitch():
global bulb
if bulb == False:
print("The light is off")
time.sleep(0.1)
bulb = True
else:
print("The light is on")
time.sleep(0.1)
bulb = False
while True:
keyboard.add_hotkey("up", LightSwitch)
keyboard.wait()

Resources