I have a program that spams messages, but I need to make such a hot key that will stop the loop, how can I do this?
I trying do this with failsafe, while True wait key, add_hotkey, but it doesn't work
(Sorry for comments in Russian.)
import codecs
import sys
import time
from pathlib import Path
import colorama
import keyboard
from Tools.i18n.makelocalealias import pprint
from art import text2art
import yaml
import pyautogui as pag
pag.FAILSAFE = True
colorama.init()
# Клавиша для активации
hotkey = "9"
# Клавиша для открытия чата
open_hotkey = "shift+t"
# Включить кнопку открытия чата
enable_open_chat_hotkey = True
# Клавиша для отправки сообщения
send_msg_hotkey = "enter"
# Интервал между символами
character_interval = 0
# Интервал между сообщениями
interval = 0.15
close_hotkey = "H+J"
can_run = True
def initConfig():
global hotkey, open_hotkey, enable_open_chat_hotkey, send_msg_hotkey, character_interval, interval, close_hotkey
if Path("config.yml").is_file():
with codecs.open('config.yml', encoding="UTF-8") as f:
loadedConfig = yaml.safe_load(f)
hotkey = loadedConfig['hotkey']
open_hotkey = loadedConfig['open_hotkey']
enable_open_chat_hotkey = loadedConfig['enable_open_chat_hotkey']
send_msg_hotkey = loadedConfig['send_msg_hotkey']
character_interval = loadedConfig['character_interval']
interval = loadedConfig['interval']
close_hotkey = loadedConfig['close_hotkey']
print(
f"Клавиша активации: {hotkey}\n"
f"Клавиша открытия чата (если включено): {open_hotkey}\n"
f"Включить ли клавишу для открытия чата в играх?: " + ("Нет", "Да")[enable_open_chat_hotkey] + "\n"
f"Интервал между символами: {character_interval}\n"
f"Интервал между сообшениями (рекомендуем оставить 0.2, меньше Дота не тянет): {interval}\n"
f"Клавиша деактивации: {close_hotkey}\n"
)
def main():
print(text2art("1000-7 SCRIPT", "standart"))
print(
"Привет, твои текущие настройки программы: \n")
initConfig()
keyboard.add_hotkey(hotkey, lambda: print_1000_7())
keyboard.wait()
def invert_run():
global can_run
can_run = not can_run
print(can_run)
def print_1000_7():
print("What is 1000-7?")
if enable_open_chat_hotkey:
keyboard.press_and_release(open_hotkey)
keyboard.press_and_release('ctrl+a')
keyboard.press_and_release('backspace')
time.sleep(interval)
keyboard.write("What is 1000-7?", character_interval)
keyboard.press_and_release(send_msg_hotkey)
keyboard.press_and_release('ctrl+a')
keyboard.press_and_release('backspace')
keyboard.press_and_release('F9')
keyboard.write("What is 1000-7?")
keyboard.press_and_release(send_msg_hotkey)
if enable_open_chat_hotkey:
keyboard.press_and_release(open_hotkey)
for i in range(5):
if not can_run:
return
print(5 - i)
if enable_open_chat_hotkey:
keyboard.press_and_release(open_hotkey)
keyboard.press_and_release('ctrl+a')
keyboard.press_and_release('backspace')
time.sleep(interval)
keyboard.write(str(5-i), character_interval)
keyboard.press_and_release(send_msg_hotkey)
time.sleep(1)
x = 1000
while x > 0:
if not can_run:
return
var = x - 7
if enable_open_chat_hotkey:
keyboard.press_and_release(open_hotkey)
keyboard.press_and_release('ctrl+a')
keyboard.press_and_release('backspace')
time.sleep(interval)
keyboard.write(f"{x} - 7 = {var}", character_interval)
# print(f"{x} - 7 = {var}")
x = var
time.sleep(interval)
keyboard.press_and_release(send_msg_hotkey)
if __name__ == '__main__':
main()
while True:
keyboard.wait(close_hotkey)
invert_run()
I'm still new to python so I'm sure this is not the best answer, also as much as i could understand you want to create a ON\OFF hotkey and i wanted to do same in some program before, so i made sure that my whole program runs only if variable a==True
and i made a hotkey that changes the 'a', so can u do same ? i mean make whole code work only if 'a' variable is set to True
[ofcourse if there is a 'while True' loop inside one of those spam then im not sure that this will work...]
a=True
def b():
global a
while a :
sleep(0.10)
keyboard.press_and_release('F2')
for i in range(45):
sleep(0.1)
if keyboard.is_pressed('e') :#this is my fail-safe cuz in my program
#i didnt want to wait for the full 4.5 sec in case i wanted to stop
a=False
keyboard.press_and_release('f')
sleep(0.1)
b()
while not a:
if keyboard.is_pressed('e') :
a=True
sleep(0.5)
b()
or another version of it
a=True
def Endb():
global a
if a==False:
a=True
else:
a=False
keyboard.add_hotkey('e',lambda: Endb())
def b():
global a
while a :
sleep(0.10)
keyboard.press_and_release('F2')
for i in range(45):
sleep(0.1)
keyboard.press_and_release('f')
sleep(0.1)
b()
while True :
if keyboard.is_pressed('e'):
Endb()
b()
this one starts\stops when ever i press 'e' as a toggle for On\Off too, and it saves me the trouble of putting the if keyboard.is_pressed('e'): a=False in every step in case i have long code like you
I fixed this problem, i just use keyboard.add_hotkey(hotkey, lambda: on_off(), suppress=True)
and
def on_off():
global enabled
enabled = not enabled
Clarificaition
This is a repost of my previous question as I am extremely desperate to receive an answer to my problem. I am quite new and if this is against any of the rules, please inform me as I would remove this post if so.
I want to create a quiz-like program where the user would be able to see the countdown timer ticking down every second while they can input their answer at any time. According to my previous post regarding this question, I've tried using threading in my code. Here is a sample of my code.
from threading import Thread
import time
import sys
def func1():
t = 10
for t in range (t,1,-1):
sys.stdout.write('\r' + str(t))
sys.stdout.flush()
time.sleep(1)
if __name__ == '__main__':
Thread(target = func1).start()
answer = input("\tEnter: ")
It does function, but the problem is that the user input is forced to return back (\r) while the timer doesn't properly remove the '0' of the 10 which is not what I desire. Here is the output:
It would be a tremendous help if you could suggest a solution to this problem. Thank you in advance.
After some messing around, I came up with this.
If you would like me to edit this to make it work without the windows, let me know.
import time
import tkinter
from tkinter import messagebox
from tkinter import *
from tkinter import ttk
from threading import Thread
def clear():
print('\033[H\033[J', end='')
run = True
def timer():
tim = int(input("Type how long the countdown should last in seconds: "))
clear()
count = 0
while count < tim and run == True:
clear()
b1 = (tim-count)
c = (str(b1),"second(s) left")
win = Tk()
win = Tk()
win.attributes('-fullscreen', True)
if run == False:
win.destroy()
Label(win, text= c,
font=('Helvetica 20 bold')).pack(pady=20)
win.after(1000,lambda:win.destroy())
win.mainloop()
time.sleep(1)
count += 1
def take_input():
inpu = input()
#Your code
def time_input():
global run
while run == True:
t1 = Thread(target=timer)
t2 = Thread(target=take_input)
t1.start()
t2.start()
t2.join()
thread_running = False
run = False
time_input()
Hope this helps, and you're welcome. 乇卩丨匚卄乂尺
(To stop the window from being fullscreen, change the (window).attributes('-fullscreen', True) to (window).geometry(500x500) or whatever you wish.
So I'm creating a Password Manager, and as a security feature I wanted to add session time that logs the user out after some time of inactivity (in the example code 3 seconds), and I have this code :
import os
import time
import threading
# Checks what OS you're using
def check_platform():
if os.name == "nt":
platform = "Windows"
else:
platform = "Linux"
return platform
# Starts inactivity timer
def start_timer():
platform = check_platform()
if platform == "Windows":
def timer_start():
while True:
time.sleep(1)
check_if_idle_windows()
thread1 = threading.Thread(target=timer_start)
thread1.start()
elif platform == "Linux":
def timer_start():
while True:
time.sleep(1)
check_if_idle_linux()
thread1 = threading.Thread(target=timer_start)
thread1.start()
# Checks if the user is idle on Windows
def check_if_idle_windows():
import win32api
idle_time = (win32api.GetTickCount() - win32api.GetLastInputInfo()) / 1000.0
if idle_time > 3:
os.system("cls")
print("You have been logged out due to inactivity.")
os._exit(0)
# Checks if the user is idle on Linux
def check_if_idle_linux():
### Code to get idle time here ###
if idle_time > 3:
os.system("clear")
print("You have been logged out due to inactivity.")
os._exit(0)
def random_function_for_main_thread():
while True:
my_string = input("Enter something or stay inactive for 3 seconds : ")
print("You entered something.")
def main():
start_timer()
random_function_for_main_thread()
if __name__ == "__main__":
main()
What can I use to get idle time on Linux?
I tried this and this, and neither of them worked.
Hope my question isn't repeated, thank you.
import os
import time
import threading
# Starts inactivity timer
def start_timer():
platform = check_platform()
if platform == "Windows":
def timer_start():
while True:
time.sleep(1)
check_if_idle_windows()
thread1 = threading.Thread(target=timer_start)
thread1.start()
elif platform == "Linux":
def timer_start():
while True:
time.sleep(1)
check_if_idle_linux()
thread1 = threading.Thread(target=timer_start)
thread1.start()
# Checks what OS you're using
def check_platform():
if os.name == "nt":
platform = "Windows"
else:
platform = "Linux"
return platform
# Checks if the user is idle on Windows
def check_if_idle_windows():
import win32api
idle_time = (win32api.GetTickCount() - win32api.GetLastInputInfo()) / 1000.0
if idle_time > 3:
os.system("cls")
print("You have been logged out due to inactivity.")
os._exit(0)
# Checks if the user is idle on Linux
def check_if_idle_linux():
import subprocess
idle_time = int(subprocess.getoutput('xprintidle')) / 1000 # Requires xprintidle (sudo apt install xprintidle)
if idle_time > 3:
os.system("clear")
print("You have been logged out due to inactivity.")
os._exit(0)
def random_function_for_main_thread():
while True:
my_string = input("Enter something or stay inactive for 3 seconds : ")
print("You entered something.")
def main():
start_timer()
random_function_for_main_thread()
if __name__ == "__main__":
main()
I'm trying to create a timer that starts when a condition for an if statement is met and then stops and returns the duration when elif condition is met, is this possible?
The purpose of the application is to send a true or false value to AWS IoT from an Android application. The Python script is subscribed to AWS and receives the value and uses it to determine whether the led should be on or off.
The code I have:
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
import RPi.GPIO as GPIO
import sys
import logging
import time
from time import sleep
from timeit import default_timer as timer
import getopt
import grovepi
msgpay = None
# Custom MQTT message callback
def customCallback(client, userdata, message):
print("Received a new message: ")
print(message.payload)
print("from topic: ")
print(message.topic)
print("--------------\n\n")
global msgpay
msgpay = message.payload
led = 5
grovepi.pinMode(led, "OUTPUT")
start_time = timer()
if msgpay == "true":
print("turning on")
grovepi.digitalWrite(led, 1)
#time.sleep(3)
elif msgpay == "false":
print("turning off")
grovepi.digitalWrite(led, 0)
duration = timer() - start_time
print duration
Any help how to go about this would be appreciated.
Thanks
I am reading serial data and writing to a csv file using a while loop. I want the user to be able to kill the while loop once they feel they have collected enough data.
while True:
#do a bunch of serial stuff
#if the user presses the 'esc' or 'return' key:
break
I have done something like this using opencv, but it doesn't seem to be working in this application (and i really don't want to import opencv just for this function anyway)...
# Listen for ESC or ENTER key
c = cv.WaitKey(7) % 0x100
if c == 27 or c == 10:
break
So. How can I let the user break out of the loop?
Also, I don't want to use keyboard interrupt, because the script needs to continue to run after the while loop is terminated.
The easiest way is to just interrupt it with the usual Ctrl-C (SIGINT).
try:
while True:
do_something()
except KeyboardInterrupt:
pass
Since Ctrl-C causes KeyboardInterrupt to be raised, just catch it outside the loop and ignore it.
There is a solution that requires no non-standard modules and is 100% transportable:
import _thread
def input_thread(a_list):
raw_input() # use input() in Python3
a_list.append(True)
def do_stuff():
a_list = []
_thread.start_new_thread(input_thread, (a_list,))
while not a_list:
stuff()
the following code works for me. It requires openCV (import cv2).
The code is composed of an infinite loop that is continuously looking for a key pressed. In this case, when the 'q' key is pressed, the program ends. Other keys can be pressed (in this example 'b' or 'k') to perform different actions such as change a variable value or execute a function.
import cv2
while True:
k = cv2.waitKey(1) & 0xFF
# press 'q' to exit
if k == ord('q'):
break
elif k == ord('b'):
# change a variable / do something ...
elif k == ord('k'):
# change a variable / do something ...
For Python 3.7, I copied and changed the very nice answer by user297171 so it works in all scenarios in Python 3.7 that I tested.
import threading as th
keep_going = True
def key_capture_thread():
global keep_going
input()
keep_going = False
def do_stuff():
th.Thread(target=key_capture_thread, args=(), name='key_capture_thread', daemon=True).start()
while keep_going:
print('still going...')
do_stuff()
pip install keyboard
import keyboard
while True:
# do something
if keyboard.is_pressed("q"):
print("q pressed, ending loop")
break
Here is a solution that worked for me. Got some ideas from posts here and elsewhere. Loop won't end until defined key (abortKey) is pressed. The loop stops as fast as possible and does not try to run to next iteration.
from pynput import keyboard
from threading import Thread
from time import sleep
def on_press(key, abortKey='esc'):
try:
k = key.char # single-char keys
except:
k = key.name # other keys
print('pressed %s' % (k))
if k == abortKey:
print('end loop ...')
return False # stop listener
def loop_fun():
while True:
print('sleeping')
sleep(5)
if __name__ == '__main__':
abortKey = 't'
listener = keyboard.Listener(on_press=on_press, abortKey=abortKey)
listener.start() # start to listen on a separate thread
# start thread with loop
Thread(target=loop_fun, args=(), name='loop_fun', daemon=True).start()
listener.join() # wait for abortKey
pyHook might help. http://sourceforge.net/apps/mediawiki/pyhook/index.php?title=PyHook_Tutorial#tocpyHook%5FTutorial4
See keyboard hooks; this is more generalized-- if you want specific keyboard interactions and not just using KeyboardInterrupt.
Also, in general (depending on your use) I think having the Ctrl-C option still available to kill your script makes sense.
See also previous question: Detect in python which keys are pressed
There is always sys.exit().
The system library in Python's core library has an exit function which is super handy when prototyping.
The code would be along the lines of:
import sys
while True:
selection = raw_input("U: Create User\nQ: Quit")
if selection is "Q" or selection is "q":
print("Quitting")
sys.exit()
if selection is "U" or selection is "u":
print("User")
#do_something()
I modified the answer from rayzinnz to end the script with a specific key, in this case the escape key
import threading as th
import time
import keyboard
keep_going = True
def key_capture_thread():
global keep_going
a = keyboard.read_key()
if a== "esc":
keep_going = False
def do_stuff():
th.Thread(target=key_capture_thread, args=(), name='key_capture_thread', daemon=True).start()
i=0
while keep_going:
print('still going...')
time.sleep(1)
i=i+1
print (i)
print ("Schleife beendet")
do_stuff()
This is the solution I found with threads and standard libraries
Loop keeps going on until one key is pressed
Returns the key pressed as a single character string
Works in Python 2.7 and 3
import thread
import sys
def getch():
import termios
import sys, tty
def _getch():
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
return _getch()
def input_thread(char):
char.append(getch())
def do_stuff():
char = []
thread.start_new_thread(input_thread, (char,))
i = 0
while not char :
i += 1
print "i = " + str(i) + " char : " + str(char[0])
do_stuff()
From following this thread down the rabbit hole, I came to this, works on Win10 and Ubuntu 20.04. I wanted more than just killing the script, and to use specific keys, and it had to work in both MS and Linux..
import _thread
import time
import sys
import os
class _Getch:
"""Gets a single character from standard input. Does not echo to the screen."""
def __init__(self):
try:
self.impl = _GetchWindows()
except ImportError:
self.impl = _GetchUnix()
def __call__(self): return self.impl()
class _GetchUnix:
def __init__(self):
import tty, sys
def __call__(self):
import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
class _GetchWindows:
def __init__(self):
import msvcrt
def __call__(self):
import msvcrt
msvcrt_char = msvcrt.getch()
return msvcrt_char.decode("utf-8")
def input_thread(key_press_list):
char = 'x'
while char != 'q': #dont keep doing this after trying to quit, or 'stty sane' wont work
time.sleep(0.05)
getch = _Getch()
char = getch.impl()
pprint("getch: "+ str(char))
key_press_list.append(char)
def quitScript():
pprint("QUITTING...")
time.sleep(0.2) #wait for the thread to die
os.system('stty sane')
sys.exit()
def pprint(string_to_print): #terminal is in raw mode so we need to append \r\n
print(string_to_print, end="\r\n")
def main():
key_press_list = []
_thread.start_new_thread(input_thread, (key_press_list,))
while True:
#do your things here
pprint("tick")
time.sleep(0.5)
if key_press_list == ['q']:
key_press_list.clear()
quitScript()
elif key_press_list == ['j']:
key_press_list.clear()
pprint("knock knock..")
elif key_press_list:
key_press_list.clear()
main()
This may be helpful
install pynput with --
pip install pynput
from pynput.keyboard import Key, Listener
def on_release(key):
if key == Key.esc:
# Stop listener
return False
# Collect events until released
while True:
with Listener(
on_release=on_release) as listener:
listener.join()
break
Here is a simple Windows solution that safely ends current iteration and then quits. I used it with a counter example that breaks the loop with 'Esc' key and quits. It uses kbhit() and getch() functions from msvcrt package. Time package is only called for easement reasons (to set time delay between events).
import msvcrt, time
print("Press 'Esc' to stop the loop...")
x = 0
while True:
x += 1
time.sleep(0.5)
print(x)
if msvcrt.kbhit():
if msvcrt.getch() == b'\x1b':
print("You have pressed Esc! See you!")
time.sleep(2)
break
kbhit() function returns True if a keypress is waiting to be read
getch() function reads a keypress and returns the resulting character as a byte string. It can be used with any key
b'\x1b' is the byte string character for the 'Esc' key.
Here another example using threading.Event, without the need for catching SIGINT (Ctrl+c).
As #Atcold has mentioned in a comment below the accepted answer, pressing Ctrl+c in the loop, may interrupt a long running operation and leave it in an undefined state. This can specially annoying, when that long running operation comes from a library that you are calling.
In the example below, the user needs to press q and then press Enter. If you want to capture the key stroke immediately, you need something like _Getch() from this answer.
import time
from threading import Thread, Event
def read_input(q_entered_event):
c = input()
if c == "q":
print("User entered q")
q_entered_event.set()
def do_long_running_stuff():
q_pressed_event = Event()
input_thread = Thread(target=read_input,
daemon=True,
args=(q_pressed_event,))
input_thread.start()
while True:
print("I am working ...")
time.sleep(1)
if q_pressed_event.is_set():
break
print("Process stopped by user.")
if __name__ == "__main__":
do_long_running_stuff()
from time import sleep
from threading import Thread
import threading
stop_flag = 0
def Wait_Char():
global stop_flag
v = input("Enter Char")
if(v == "z"):
stop_flag = 1
def h():
while(True):
print("Hello Feto")
time.sleep(1)
if(stop_flag == 1):
break
thread1 = Thread(target=Wait_Char)
thread2 = Thread(target=h)
thread1.start()
thread2.start()
print("threads finished...exiting")
This isn't the best way but it can do the job you want,
Running 2 Threads one waiting for the Key you want to stop the loop with
(Wait_Char Method)
and one for loop
(H Method)
And both see a global variable stop_flag which control the stoping process
Stop when I press z
from pynput import keyboard
def on_press(key):
if key == keyboard.Key.esc:
return False
i = 0
with keyboard.Listener(on_press=on_press) as listener:
# Your infinite loop
while listener.running:
print(i)
i=i+1
print("Done")
It works ...
import keyboard
while True:
print('please say yes')
if keyboard.is_pressed('y'):
break
print('i got u :) ')
print('i was trying to write you are a idiot ')
print(' :( ')
for enter use 'ENTER'