problems with failsafe and threading - python

I am trying to make a python autoclicker as seen below:
import queue
from pynput import mouse
from pynput.mouse import Controller, Button
from sys import exit
from threading import Thread
from time import sleep
from keyboard import is_pressed
mouse = Controller()
failSafeKey = 'q'
delay = 1
def clicking():
while TRUE:
mouse.click(Button.left)
sleep(delay)
def failSafe():
while TRUE:
if is_pressed(failSafeKey):
exit()
print("exiting")
sleep(0.1)
delay = float(input("Enter delay: "))
failSafeKey = input("Enter failsafe key (ex. ctrl+s or q): ")
Thread(clicking())
Thread(failSafe())
However, whenever I press the failsafe key, nothing happens. I have tried removing the threads, but nothing changed. Can anyone give pointers on what might be happening?

Related

Stopping a python program when an arbitrary key was pressed while the program is running

I recently got to know about the python module signal. With that, we can capture a SIGINT and do what we want after capturing it. I used it as below. In that case I am just using SIGINT to print that program is going to be stopped and stop the program.
import signal
import os
import time
def signalHandler(signalnumb, frame):
print("Signal Number:", signalnumb, " Frame: ", frame)
print('Exiting the program...')
os._exit(0)
signal.signal(signal.SIGINT, signalHandler)
c=0
# Loop infinite times using the while(1) which is always true
while 1:
print(c)
#sleep for 1 seconds using the sleep() function in time
time.sleep(1)
c=c+1
Now I want to give any signal from keyboard(for example pressing 'q') and as soon as signal was recieved, the python program should be stopped. Has anyone got some experience on how to do that? Any other method rather than using signal module (for example using multithreading) is accepted.
Edit1-
Later I tried to use pynput module as suggested in one of a similar kind of question. For sure I have done a mistake. It doesn't work as I expected. It means with a key press, I couldn't stop the for loop from running.
from pynput import keyboard
import time
def on_press(key):
for i in range(100):
print(i)
time.sleep(1)
if key == keyboard.Key.esc:
return False # stop listener
try:
k = key.char # single-char keys
except:
k = key.name # other keys
if k in ['1', '2', 'left', 'right']: # keys of interest
# self.keys.append(k) # store it in global-like variable
print('Key pressed: ' + k)
return False # stop listener; remove this if want more keys
listener = keyboard.Listener(on_press=on_press)
listener.start() # start to listen on a separate thread
listener.join() # remove if main thread is polling self.keyspython
Can someone point out how to do it using pynput in correct way?
This was my original implementation:
a = input('Press a key to exit')
if a:
exit(0)
However, it seems that you need a piece of code that will allow for any key to be clicked and immediately exit out of the program, without hitting enter afterwards. This may be a better way to do that:
import readchar
print("Press Any Key To Exit")
k = readchar.readchar()
Hope this helps!
After carefully understanding about the threads and pynput module, I managed to stop a for loop (or any program which runs as a separate thread) using a key press callback.
from pynput import keyboard
import os
import threading
import time
loop_running = False
def on_press(key):
print(dir(key))
global loop_running
#if key == keyboard.Key.delete and not loop_running:
if ('char' in dir(key)) and (key.char == 's') and (not loop_running):
t=threading.Thread(target=start_loop)
t.start()
#elif key==keyboard.Key.tab: #if this is used, the attributes related to 'key' will be changed. you can see them since I have used a print(dir(key))
elif key.char == 'q':
loop_running=False
def start_loop():
global loop_running
loop_running = True
for i in range(100):
if not loop_running:
os._exit(0)
print(i)
time.sleep(1)
with keyboard.Listener(on_press=on_press) as listner:
listner.join()

How do I get my code to loop until I press a button (Lego EV3)

The question pure and simple. I've tried using while loops, rearranging code, but all that happens is that the program starts when i press the button or does absolutely nothing at all. Can anyone see what I am doing wrong?
#!/usr/bin/env python3
from ev3dev2.motor import MoveTank, OUTPUT_B, OUTPUT_C
from ev3dev2.button import Button
from ev3dev2.sound import Sound
from time import sleep
import time
sound = Sound()
btn = Button()
tank_pair = MoveTank(OUTPUT_B, OUTPUT_C)
def movement(left_speed, right_speed, rotations):
tank_pair.on_for_rotations(left_speed, right_speed, rotations, brake=True, block=True)
while not btn.any():
movement(20,20,10)
movement(-100,0,1.5)
movement(20,20,10)
sleep(0.01)
while btn.any():
sleep(0.01)
tank_pair.off()
sound.beep()
exit()
you can break your main loop using this
pip install keyboard
then
import keyboard
while True:
# do something
if keyboard.is_pressed("q"):
print("q pressed, ending loop")
break
Your indentation is incorrect.
from ev3dev2.motor import MoveTank, OUTPUT_B, OUTPUT_C
from ev3dev2.button import Button
from ev3dev2.sound import Sound
from time import sleep
import time
sound = Sound()
btn = Button()
tank_pair = MoveTank(OUTPUT_B, OUTPUT_C)
def movement(left_speed, right_speed, rotations):
tank_pair.on_for_rotations(left_speed, right_speed, rotations, brake=True, block=True)
while not btn.any():
movement(20,20,10)
movement(-100,0,1.5)
movement(20,20,10)
sleep(0.01)
while btn.any():
sleep(0.01)
tank_pair.off()
sound.beep()
exit()

Python Block Keyboard / Mouse Input

i am currently trying to write a short script that will rickroll (open a youtube link) while the user is watching and can't interfere.
I have managed to open insert the link slowly letter by letter and am now trying to block user inputs.
I have tried using the ctypes import to block all inputs, run the script and then unblock again, but it somehow won't block the input. I'm just receiving my RuntimeError message.
How do i fix it, so the inputs get blocked?
Thanks in advance!
Heres the code:
import subprocess
import pyautogui
import time
import ctypes
from ctypes import wintypes
BlockInput = ctypes.windll.user32.BlockInput
BlockInput.argtypes = [wintypes.BOOL]
BlockInput.restype = wintypes.BOOL
blocked = BlockInput(True)
if blocked:
try:
subprocess.Popen(["C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",])
time.sleep(3)
pyautogui.write('www.youtube.com/watch?v=DLzxrzFCyOs', interval= 0.5)
pyautogui.hotkey('enter')
finally:
unblocked = BlockInput(False)
else:
raise RuntimeError('Input is already blocked by another thread')
You can use the keyboard module to block all keyboard inputs and the mouse module to constantly move the mouse, preventing the user from moving it.
See these links for more details:
https://github.com/boppreh/keyboard
https://github.com/boppreh/mouse
This blocks all the keys on the keyboard (the 150 is large enough to ensure all keys are blocked).
#### Blocking Keyboard ####
import keyboard
#blocks all keys of keyboard
for i in range(150):
keyboard.block_key(i)
This effectively blocks mouse-movement by constantly moving the mouse to position (1,0).
#### Blocking Mouse-movement ####
import threading
import mouse
import time
global executing
executing = True
def move_mouse():
#until executing is False, move mouse to (1,0)
global executing
while executing:
mouse.move(1,0, absolute=True, duration=0)
def stop_infinite_mouse_control():
#stops infinite control of mouse after 10 seconds if program fails to execute
global executing
time.sleep(10)
executing = False
threading.Thread(target=move_mouse).start()
threading.Thread(target=stop_infinite_mouse_control).start()
#^failsafe^
And then your original code here (the if statement and try/catch block are no longer necessary).
#### opening the video ####
import subprocess
import pyautogui
import time
subprocess.Popen(["C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",])
time.sleep(3)
pyautogui.write('www.youtube.com/watch?v=DLzxrzFCyOs', interval = 0.5)
pyautogui.hotkey('enter')
#### stops moving mouse to (1,0) after video has been opened
executing = False
Just a few notes:
The mouse-moving is hard to stop from outside of the program (it's basically impossible to close the program when it is executing, especially as the keyboard is also being blocked), that's why I put in the failsafe, which stops moving the mouse to (1,0) after 10 seconds.
(On Windows) Control-Alt-Delete does allow Task Manager to be opened and then the program can be force-stopped from there.
This doesn't stop the user from clicking the mouse, which can sometimes prevent the YouTube link from being typed in full (i.e. a new tab can be opened)
See a full version of the code here:
https://pastebin.com/WUygDqbG
you could do something like this to block both keyboard and mouse input
from ctypes import windll
from time import sleep
windll.user32.BlockInput(True) #this will block the keyboard input
sleep(15) #input will be blocked for 15 seconds
windll.user32.BlockInput(False) #now the keyboard will be unblocked
Here's a function for blocking keyboard and mouse input. You can pass a number to the blockMouseAndKeys function to adjust the timeout period:
import os
import time
import pyautogui
from threading import Thread
from keyboard import block_key
def blockMouseAndKeys(timeout=5):
global blocking
blockStartTime = time.time()
pyautogui.FAILSAFE = False
blocking = True
try: float(timeout)
except: timeout = 5
def blockKeys(timeout):
global blocking
while blocking:
if timeout:
if time.time()-blockStartTime > timeout:
print(f'Keyboard block timed out after {timeout}s.')
return
for i in range(150):
try: block_key(i)
except: pass
def blockMouse(timeout):
global blocking
while blocking:
def resetMouse(): pyautogui.moveTo(5,5)
Thread(target=resetMouse).start()
if timeout:
if time.time()-blockStartTime > timeout:
print(f'Mouse block timed out after {timeout}s.')
return
def blockTimeout(timeout):
global blocking
time.sleep(timeout)
blocking = False
pyautogui.FAILSAFE = False
print('Done blocking inputs!')
print('Blocking inputs...')
Thread(target=blockKeys, args=[timeout]).start()
Thread(target=blockMouse, args=[timeout]).start()
Thread(target=blockTimeout, args=[timeout]).start()
blockMouseAndKeys(timeout=10)
os.startfile('https://www.youtube.com/watch?v=DLzxrzFCyOs')

Press a key in a batch script with Python

I have a script in python that execute a batch program that need press two or three times the "d" key and after the "q" key.
I tried this but without solution:
import os
import keyboard
import time
from pynput.keyboard import Key, Controller
os.system('"C:/Users/xxx/Documents/Software/xxx.exe 192.168.0.15"')
time.sleep(5)
keyboard = Controller()
keyd = "d"
keyq = "q"
keyboard.press(keyd)
keyboard.release(keyd)
time.sleep(3)
keyboard.press(keyq)
keyboard.release(keyq)
Only open the console but the script don't press the keys, but if you press with the keyboard the program works fine.
You could try to use the subprocess module.
Example:
subprocess-test.py
import subprocess
p = subprocess.Popen(["python", "input-app.py"], stdin=subprocess.PIPE)
p.stdin.write("Hello\n".encode(encoding='UTF-8'))
p.stdin.write("World\n".encode(encoding='UTF-8'))
input-app.py
input1 = input("Input 1: ")
input2 = input("Input 2: ")
print(input1, input2)
See more information here:
https://docs.python.org/3/library/subprocess.html
https://stackoverflow.com/a/3684694/42659
Sorry, I won't be able to help more as I only have a short lunch break. I hope this already does help though or points you in the right direction!
You can use: pyautogui for pressing code as simply as:
import pyautogui
pyautogui.press('d')
Your case can be handled as follows:
import os
import pyautogui
import time
os.system('"C:/Users/xxx/Documents/Software/xxx.exe 192.168.0.15"')
time.sleep(5)
keyd = "d"
keyq = "q"
pyautogui.press(keyd)
time.sleep(3)
pyautogui.press(keyq)
If pressing keys don't work, you may try to enter exact strings as well:
import os
import pyautogui
import time
os.system('"C:/Users/xxx/Documents/Software/xxx.exe 192.168.0.15"')
time.sleep(5)
keyd = "d"
keyq = "q"
pyautogui.write(keyd)
time.sleep(3)
pyautogui.write(keyq)

disable or lock mouse and keyboard in Python?

Is there a way of disabling or locking mouse and keyboard using python? I want to freeze the mouse and disable the keyboard.
I haven't tested (actually I've tested the mouse part, and it annoyingly works) but something like this using pyhook would do what you want:
import pythoncom, pyHook
def uMad(event):
return False
hm = pyHook.HookManager()
hm.MouseAll = uMad
hm.KeyAll = uMad
hm.HookMouse()
hm.HookKeyboard()
pythoncom.PumpMessages()
I have extended Fábio Diniz's answer to a class which provides both a block() and an unblock() function which block (selectively) mouse/keyboard inputs. I also added a timeout functionality which (hopefully) addresses the annoyance of locking oneself out.
import pyHook
from threading import Timer
import win32gui
import logging
class blockInput():
def OnKeyboardEvent(self,event):
return False
def OnMouseEvent(self,event):
return False
def unblock(self):
logging.info(" -- Unblock!")
if self.t.is_alive():
self.t.cancel()
try: self.hm.UnhookKeyboard()
except: pass
try: self.hm.UnhookMouse()
except: pass
def block(self, timeout = 10, keyboard = True, mouse = True):
self.t = Timer(timeout, self.unblock)
self.t.start()
logging.info(" -- Block!")
if mouse:
self.hm.MouseAll = self.OnMouseEvent
self.hm.HookMouse()
if keyboard:
self.hm.KeyAll = self.OnKeyboardEvent
self.hm.HookKeyboard()
win32gui.PumpWaitingMessages()
def __init__(self):
self.hm = pyHook.HookManager()
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
block = blockInput()
block.block()
import time
t0 = time.time()
while time.time() - t0 < 10:
time.sleep(1)
print(time.time() - t0)
block.unblock()
logging.info("Done.")
You can have a look at the main routine for example usage.
For me, just two lines of programming solved the problem:
from ctypes import *
ok = windll.user32.BlockInput(True) #enable block
#or
ok = windll.user32.BlockInput(False) #disable block
Totally different take since all the solutions mentioned above use a quiet outdated library(pyhook) and this pyhook method personally didnt work for me.
import keyboard
from pynput.mouse import Controller
from time import sleep
def blockinput():
global block_input_flag
block_input_flag = 1
t1 = threading.Thread(target=blockinput_start)
t1.start()
print("[SUCCESS] Input blocked!")
def unblockinput():
blockinput_stop()
print("[SUCCESS] Input unblocked!")
def blockinput_start():
mouse = Controller()
global block_input_flag
for i in range(150):
keyboard.block_key(i)
while block_input_flag == 1:
mouse.position = (0, 0)
def blockinput_stop():
global block_input_flag
for i in range(150):
keyboard.unblock_key(i)
block_input_flag = 0
blockinput()
print("now blocking")
sleep(5)
print("now unblocking")
I just slightly modified the #Robert code and instead of the time I used external interrupt to close the program i.e. if you connect any external drive then the program gets close and your mouse and keyboard will be working perfectly.
import pyHook
from threading import Timer
import win32gui
import logging
import win32file
def locate_usb():#this will check any external Drives
drive_list = []
drivebits = win32file.GetLogicalDrives()
# print(drivebits)
for d in range(1, 26):
mask = 1 << d
if drivebits & mask:
# here if the drive is at least there
drname = '%c:\\' % chr(ord('A') + d)
t = win32file.GetDriveType(drname)
if t == win32file.DRIVE_REMOVABLE:
drive_list.append(drname)
return drive_list
class blockInput():
def OnKeyboardEvent(self,event):
return False
def OnMouseEvent(self,event):
return False
def unblock(self):
try: self.hm.UnhookKeyboard()
except: pass
try: self.hm.UnhookMouse()
except: pass
def block(self ,keyboard = True, mouse = True):
while(1):
if mouse:
self.hm.MouseAll = self.OnMouseEvent
self.hm.HookMouse()
if keyboard:
self.hm.KeyAll = self.OnKeyboardEvent
self.hm.HookKeyboard()
win32gui.PumpWaitingMessages()
cg= locate_usb()
if cg:
break
def __init__(self):
self.hm = pyHook.HookManager()
if __name__ == '__main__':
block = blockInput()
block.block()
block.unblock()
I hope this code will help you
Since 2018, you can now use pynput (v1.4+) to suppress keyboard and mouse events on Windows, Mac, and Linux.
import pynput
# Disable mouse and keyboard events
mouse_listener = pynput.mouse.Listener(suppress=True)
mouse_listener.start()
keyboard_listener = pynput.keyboard.Listener(suppress=True)
keyboard_listener.start()
# Enable mouse and keyboard events
mouse_listener.stop()
keyboard_listener.stop()
This also disables mouse scrolling and clicking.
However, this does not stop users from pressing Ctrl+Alt+Del on Windows. But you can run the script in an elevated command prompt, and the mouse and keyboard will still be disabled, even if they opened Task Manager using Ctrl+Alt+Delete, so there is no harm done (apparently there are way to actually prevent Ctrl+Alt+Delete, but do your own research for that)
You can use pyautogui to do this. Though I recommend adding keyboard for making a stopping key. First, you want to install pyautogui and keyboard.
Please note: this only disables the mouse not the keyboard, that is a very bad idea.
pip install pyautogui
pip install keyboard
Ok, with that sorted, we have to actually make the disabler.
import pyautogui
import keyboard
stopKey = "s" #The stopKey is the button to press to stop. you can also do a shortcut like ctrl+s
maxX, maxY = pyautogui.size() #get max size of screen
While True:
if keyboard.is_pressed(stopKey):
break
else:
pyautogui.moveTo(maxX/2, maxY/2) #move the mouse to the center of the screen
Ok, but there is 2 ways to get out of this. pressing S, and also quickly moving the mouse to one of the corners of the screen (that is a pyautogui failsafe, but we can disable that). If you want to disable the failsafe, add this after the imports:
pyautogui.FAILSAFE = False
Please note that disabling the failsafe is NOT recommended!
Ok, so now the only way to exit is the S key. If you want to stop this somewhere else in your program, do this:
pyautogui.press(stopKey)
Ok, so its not perfect, but it will stop you from doing basically anything with your mouse.

Categories

Resources