import time
import pyautogui
from pyautogui import *
import keyboard
from PIL import ImageGrab
import os
import win32api, win32con
import cv2
import pyperclip
from pynput.keyboard import Key, Listener
import pytesseract
##1340,182, 1777, 213
test = 0
def alertf1(c):
global test
while c == 1:
if keyboard.is_pressed('f1'): # if key 'f1' is pressed
print('f1 has been pressed')
c = 0
time.sleep(0.1)
test = test + 1
break
else:
print('checking if anything is destroyed')
time.sleep(1)
if pyautogui.locateOnScreen('destroy2.png', region=(1340,182, 1777, 230)):
print('something got destroyed!')
time.sleep(0.1)
pyautogui.keyDown('ctrl')
time.sleep(0.1)
pyautogui.keyDown('tab')
pyautogui.keyUp('ctrl')
pyautogui.keyUp('tab')
time.sleep(0.5)
for char in '#':
pyperclip.copy(char)
pyautogui.hotkey('ctrl', 'v', interval=0.1)
time.sleep(0.1)
pyautogui.write('everyone Enemies/Red Logs! Something has been destroyed.')
time.sleep(0.1)
pyautogui.press('enter')
time.sleep(5)
pyautogui.click(x=1860, y=50)
time.sleep(5)
else:
if keyboard.is_pressed('f1'): # if key 'f1' is pressed
print('f1 has been pressed')
c = 0
time.sleep(0.1)
test = test + 1
break
def on_press(key):
global test
if test > 0 and key == Key.f1:
c = 0
if key == Key.f1 and test == 0:
print('before alert f1 pressed')
time.sleep(0.1)
test = test + 1
alertf1(1)
if key == Key.f1 and test > 1:
test = 0
with Listener(on_press=on_press) as listener:
listener.join()
def main():
while True:
time.sleep(0.1)
print('on press going now')
on_press(key)
if __name__ == '__main__':
main()
my issue is that i want the turn on / off switch to use hte same key
and i can't think of a way to distinguish between when I press the key and when the program is simply on loop.
like F1 will start function alert, which will loop eternally, until I press F1, issue is that, if keyboard.is_pressed('f1'): isn't a great solution
because if code is somewhere else it wont recognize i pressed f1
Related
I am trying to stop a while loop mid execution, if I reverse the value of 'runWhile' mid execution it simply waits until it's over.
Problem: I need it to stop immediately whenever I press f10 on the keyboard.
from pynput import keyboard
import threading
import datetime, time
def exec():
while runWhile:
print("There I go")
time.sleep(3)
print("I overtaken")
time.sleep(3)
print("You cant stop me until I finish")
def on_press(key):
global runWhile # inform function to assign (`=`) to external/global `running` instead of creating local `running`
if key == keyboard.Key.f5:
runWhile = True
t = threading.Thread(target=exec)
t.start()
if key == keyboard.Key.f10:
# to stop loop in thread
print("loading STOPPED", datetime.datetime.now()) #, end='\r')
runWhile = False
if key == keyboard.Key.f11:
# stop listener
print("listener TERMINATED", datetime.datetime.now()) #, end='\r')
return False
#--- main ---
with keyboard.Listener(on_press=on_press) as listener:
listener.join()
Im using pynput, docs here
based on #furas code
Here is a solution I made. I created my own delay function as follows:
def delay(amount): #delay time in seconds
for i in range(int(amount*60)):
time.sleep(0.01)
if runWhile == False:
return True
break
You would replace your delay(3) with
if delay(3):
break
This would wait 3 seconds, however if during that time, runWhile was false, it will break out of the loop. Your code would look like this:
from pynput import keyboard
import threading
import datetime, time
def delay(amount): #delay time in seconds
for i in range(int(amount*60)):
time.sleep(0.01)
if runWhile == False:
return True
break
def exec():
while runWhile:
print("There I go")
if delay(3):
break
print("I overtaken")
if delay(3):
break
print("You cant stop me until I finish")
def on_press(key):
global runWhile # inform function to assign (`=`) to external/global `running` instead of creating local `running`
if key == keyboard.Key.f5:
runWhile = True
t = threading.Thread(target=exec)
t.start()
if key == keyboard.Key.f10:
# to stop loop in thread
print("loading STOPPED", datetime.datetime.now()) #, end='\r')
runWhile = False
if key == keyboard.Key.f11:
# stop listener
print("listener TERMINATED", datetime.datetime.now()) #, end='\r')
return False
#--- main ---
with keyboard.Listener(on_press=on_press) as listener:
listener.join()
I am building some macro program using pyautogui.
Unfortunately I am not able to stop for-loop so sometimes it takes too much time until for-loop end.
Is there any way to stop the program at any moment I want? or I just wait until program end.
below is my code
CURRENT_DIR = os.getcwd()
list = os.path.join(CURRENT_DIR,'BOM_list.xlsx')
df = pd.read_excel(list)
for i in df['MLFB'].index:
MLFB = df.loc[i, 'MLFB']
print(MLFB)
a = pyautogui.locateCenterOnScreen('a_material.png')
print(a)
pyautogui.moveTo(a)
pyautogui.moveRel(350, 0)
pyautogui.click()
pyautogui.keyDown('ctrl')
pyautogui.press('a')
pyautogui.keyUp('ctrl')
pyautogui.typewrite(MLFB)
b = pyautogui.locateCenterOnScreen('b_execute.png')
print(b)
pyautogui.moveTo(b)
pyautogui.click()
time.sleep(2.5)
pyautogui.keyDown('alt')
pyautogui.press('y')
pyautogui.press('t')
pyautogui.press('a')
pyautogui.press('i')
pyautogui.keyUp('alt')
time.sleep(2)
pyautogui.press('down')
pyautogui.typewrite(['enter'])
time.sleep(2)
c = pyautogui.locateCenterOnScreen('c_Directory.png')
pyautogui.moveTo(c)
pyautogui.moveRel(350, 0)
pyautogui.click()
pyautogui.keyDown('ctrl')
pyautogui.press('a')
pyautogui.keyUp('ctrl')
pyautogui.typewrite(CURRENT_DIR)
pyautogui.click()
time.sleep(1.5)
d = pyautogui.locateCenterOnScreen('d_Filename.png')
pyautogui.moveTo(d)
pyautogui.moveRel(350, 0)
pyautogui.click()
pyautogui.keyDown('ctrl')
pyautogui.press('left')
pyautogui.keyUp('ctrl')
pyautogui.typewrite(MLFB)
time.sleep(0.5)
pyautogui.typewrite(['enter'])
time.sleep(2)
e = pyautogui.locateCenterOnScreen('e_go_back.png')
pyautogui.moveTo(e)
pyautogui.click()
time.sleep(2)
PyAutoGUI has a built in failsafe to terminate the program at any time. Just move your mouse to the top left corner of your main monitor where your x, y values would be 0, 0.
Typing print(pyautogui.FAILSAFE) should return True, telling us the failsafe is on. You could also disable it if it's getting in the way of your program by setting it to pyautogui.FAILSAFE = False
Looking through your code, you could save some space by using hotkey() when you want to press more than one key at a time:
pyautogui.keyDown('ctrl')
pyautogui.press('a')
pyautogui.keyUp('ctrl')
Is the same as:
pyautogui.hotkey('ctrl', 'a')
You could also check out threading which allows you to run more than one process at a time.
The following code will have an example main program running and when the Esc key is pressed, the main program will pause and the user is prompted if they want to continue or not.
import time
from threading import Thread
from pynput import keyboard
def exit_program():
def on_press(key):
if str(key) == 'Key.esc':
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()
Im trying to move my Cursor every three seconds and if it went too far, reset it to its original location. I want the program to stop after I press any key on the keyboard.
It doesnt seem to work though... what could I be missing? This is what I came up with:
import win32api, win32con, time, sys, msvcrt
global z
z=10
def kbfunc():
#this is boolean for whether the keyboard has bene hit
x = msvcrt.kbhit()
if x:
sys.exit
else:
ret = False
return ret
def move(x,y):
win32api.mouse_event(win32con.MOUSEEVENTF_MOVE | win32con.MOUSEEVENTF_ABSOLUTE, int(x/1920*65535.0), int(y/1080*65535.0))
while True:
move(960,540+z)
time.sleep(3)
if z>100:
move(960,540)
z += -100
z + 10
kbfunc()
First, you need to install the keyboard module:
pip3 install keyboard
And than add it to your loop:
import keyboard
while True:
move(960,540+z)
time.sleep(3)
if z>100:
move(960,540)
z += -100
z + 10
if keyboard.is_pressed('q'): # if key 'q' is pressed
print('You Pressed A Key!')
break # finishing the loop
I would guess that msvcrt.kbhit() does not store previous hits. It only tells you if a key is hit at the current moment in time. You can loop checking for keyboard hits. If no hits before 3 seconds, return:
import time
import msvcrt
import sys
def kbfunc(max_time=3):
start = time.time()
while not msvcrt.kbhit():
end = time.time()
if end - start >= max_time:
break
else:
sys.exit()
After trying around with the given answers, the finished solution looks like this:
global z
z=10
def move():
mouse.move(10, 10, absolute=False, duration=1)
def moveback():
mouse.move(-10, -10, absolute=False, duration=1)
while True:
move()
time.sleep(3)
moveback()
if keyboard.is_pressed('q'): # if key 'q' is pressed
break # finishing the loop
I want to make clicker for my game and i don't know how can I exit program after I press a key. I've tried
import sys
screenWidth, screenHeight = pyautogui.size()
currentMouseX, currentMouseY = pyautogui.position()
if keyboard.is_pressed("p"):
sys.exit()
for user in range(0, 1):
pyautogui.moveTo(849, 657) # załóż druzyne
pyautogui.click()
pyautogui.PAUSE = 0.2
pyautogui.typewrite('Bandaelo')
pyautogui.PAUSE = 0.3
pyautogui.moveTo(953, 742) # potwierdź
pyautogui.click()
pyautogui.PAUSE = 0.4
pyautogui.moveTo(948, 656) # potwierdz
pyautogui.click()
and more code like this
but it doesn't work. Can You help me?
This should do the trick, you still need to put your code:
import sys
import pyautogui
def main():
screenWidth, screenHeight = pyautogui.size()
currentMouseX, currentMouseY = pyautogui.position()
try:
while 1:
var = input("enter p to exit: ")
if var == 'p':
break
else:
print('test something')
# put your code here...
# and more code like this
except KeyboardInterrupt:
sys.exit()
raise
if __name__ == '__main__':
main()
You need to import sys object. Then call the exit() method to stop your program.
For your case you can try:
import keyboard
import sys
if keyboard.is_pressed("p"):
sys.exit()
EDIT : I have done a little research and find when writing a multithreaded app, raise SystemExit and sys.exit() both terminates only the running thread. In this case, you can use os._exit() which exits the whole process.
import os
import keyboard
if keyboard.is_pressed('p'):
os._exit(0)
How can I run a timer while asking for user input from the console? I was reading about multiprocessing, and I tried to use this answer: Python: Executing multiple functions simultaneously. When I tried to get it going, it gave me a bunch of framework errors.
Right now it runs start_timer(), but then stops it when it runs cut_wire().
Here's my start_timer function:
def start_timer():
global timer
timer = 10
while timer > 0:
time.sleep(1)
timer -= 1
sys.stdout.write ("There's only %i seconds left. Good luck. \r" % (timer))
sys.stdout.flush()
cut_wire()
if timer == 0:
print("Boom!")
sys.exit()
and this is the cut_wire function:
def cut_wire():
wire_choice = raw_input("\n> ")
if wire_choice == "cut wire" or wire_choice == "Cut Wire":
stop_timer()
else:
print("Boom!")
sys.exit()
Of course it stops running when it plays the cut_wire function because "raw_input" command reads the text and wait for the user to put the text and press enter.
My suggestion is to check for they key press "Enter" and when then key was press, read the line. If the key wasn't press, just continue with your timer.
Regards.
Instead of using raw_input() use this function taken from here.
def readInput( caption, timeout = 1):
start_time = time.time()
sys.stdout.write('\n%s:'%(caption));
input = ''
while True:
if msvcrt.kbhit():
chr = msvcrt.getche()
if ord(chr) == 13: # enter_key
break
elif ord(chr) >= 32: #space_char
input += chr
if len(input) == 0 and (time.time() - start_time) > timeout:
break
print '' # needed to move to next line
if len(input) > 0:
return input
else:
return ""
Thearding option
To make sure that both functions run completely simultaneously you can use this example of threading event:
import threading
event = threading.Event()
th = theading.Thread(target=start_timer, args=(event, ))
th1 = theading.Thread(target=cut_wire, args=(event, ))
th.start()
th1.start()
th.join()
th1.join()
In your function you can set an event using event.set(), check it using event.is_set() and clear it using event.clear().
Only addressing your concerns, here is a quick fix using threading :
import time
import sys
import os
def start_timer():
global timer
timer = 10
while timer > 0:
time.sleep(1)
timer -= 1
sys.stdout.write ("There's only %i seconds left. Good luck. \r" % (timer))
sys.stdout.flush()
#cut_wire() ==> separate call is easier to handle
if timer == 0:
print("Boom!")
os._exit(0) #sys.exit() only exits thread
def cut_wire():
wire_choice = raw_input("\n> ")
if wire_choice == "cut wire" or wire_choice == "Cut Wire":
stop_timer()
else:
print("Boom!")
os._exit(0) #same reason
if __name__ == '__main__':
import threading
looper = threading.Thread(target=start_timer)
looper.start()
cut_wire()