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
Related
I have a Python script where I would like to replace the sleep() with wait in order to interrupt the threads instantly even when they are sleeping.
However I don't know how to transform my functions into Events.
I read that asyncio could also be used but I am not sure to understand how it works.
Here is the code :
from pynput import keyboard
from pynput.keyboard import Key, Controller
import datetime
import time
import threading
import random
import pyautogui
from threading import Event
# --- functions ---
keyboardCtrl = Controller()
def run():
print('Running thread')
time.sleep(random.randrange(150,350)/1000)
while running:
my_keylist1=['e']
while len(my_keylist1) > 0:
n = random.choice(my_keylist1)
keyboardCtrl.press(n)
#print('Time:',datetime.datetime.now(),n)
my_keylist1.remove(n)
time.sleep(random.randrange(10200,10450)/1000)
print('Exiting thread 1')
def run2():
time.sleep(random.randrange(150,350)/1000)
while running:
pyautogui.keyDown('z')
#print('T2',datetime.datetime.now())
#time.sleep(random.randrange(1000,3000)/1000)
print('Exiting thread 2')
pyautogui.keyUp('z')
def run3():
time.sleep(random.randrange(150,350)/1000)
while running:
my_keylist1=['f']
while len(my_keylist1) > 0:
n = random.choice(my_keylist1)
keyboardCtrl.press(n)
#print('Time:',datetime.datetime.now(),n)
my_keylist1.remove(n)
time.sleep(random.randrange(6250,6550)/1000)
print('Exiting thread 3')
def on_press(key):
global running # inform function that it has to assign value to external variable
global clicker
global clicker2,clicker3
try: # PEP8: don't put it in one line - it make code unreadable for human
k = key.char
except:
k = key.name
if key == keyboard.KeyCode(char='q'):
print("Key Pressed")
if not running: # the same as `if running == False:`
print("Starting thread")
clicker = threading.Thread(target=run)
clicker2 = threading.Thread(target=run2)
clicker3 = threading.Thread(target=run3)
running = True # it has to be before `start()`
clicker.start()
clicker2.start()
clicker3.start()
else:
print("Stopping thread")
running = False # it has to be before `join()`
clicker.join()
clicker2.join()
clicker3.join()
# press `F1` to exit
if key == keyboard.Key.f1:
return False
# --- main ---
running = False # default value at start
try:
print("Starting program")
print("- press E to start/stop thread")
print("- press F1 to exit")
print("- press Ctrl+C to exit")
lis = keyboard.Listener(on_press=on_press)
lis.start()
print("Listening ...")
lis.join()
print("Exiting program")
except KeyboardInterrupt:
print("Stoped by Ctrl+C")
else:
print("Stoped by F1")
finally:
if running:
running = False
clicker.join()
clicker2.join()
clicker3.join()
Maybe you can try something like, I am sure there is a better solution, I would suggest reading the documentation.
import asyncio
from pynput import keyboard
from pynput.keyboard import Key, Controller
import datetime
import time
import threading
import random
import pyautogui
from threading import Event
# --- functions ---
keyboardCtrl = Controller()
async def run():
print('Running thread')
await asyncio.sleep(random.randrange(150, 350) / 1000)
while running:
my_keylist1 = ['e']
while len(my_keylist1) > 0:
n = random.choice(my_keylist1)
keyboardCtrl.press(n)
# print('Time:',datetime.datetime.now(),n)
my_keylist1.remove(n)
#time.sleep(random.randrange(10200, 10450) / 1000)
await asyncio.sleep(random.randrange(10200, 10450) / 1000)
print('Exiting thread 1')
async def run2():
#time.sleep(random.randrange(150, 350) / 1000)
await asyncio.sleep(random.randrange(150, 350) / 1000)
while running:
pyautogui.keyDown('z')
# print('T2',datetime.datetime.now())
# time.sleep(random.randrange(1000,3000)/1000)
print('Exiting thread 2')
pyautogui.keyUp('z')
async def run3():
#time.sleep(random.randrange(150, 350) / 1000)
await asyncio.sleep(random.randrange(150, 350) / 1000)
while running:
my_keylist1 = ['f']
while len(my_keylist1) > 0:
n = random.choice(my_keylist1)
keyboardCtrl.press(n)
# print('Time:',datetime.datetime.now(),n)
my_keylist1.remove(n)
#time.sleep(random.randrange(6250, 6550) / 1000)
await asyncio.sleep(random.randrange(6250, 6550) / 1000)
print('Exiting thread 3')
async def on_press(key):
global running # inform function that it has to assign value to external variable
global clicker
global clicker2, clicker3
try: # PEP8: don't put it in one line - it make code unreadable for human
k = key.char
except:
k = key.name
if key == keyboard.KeyCode(char='q'):
print("Key Pressed")
if not running: # the same as `if running == False:`
print("Starting thread")
#await run()
#await run2()
#await run3()
await asyncio.gather(*[run(), run2(), run3()])
#clicker = threading.Thread(target=run)
#clicker2 = threading.Thread(target=run2)
#clicker3 = threading.Thread(target=run3)
running = True # it has to be before `start()`
#clicker.start()
#clicker2.start()
#clicker3.start()
else:
print("Stopping thread")
running = False # it has to be before `join()`
#clicker.join()
#clicker2.join()
#clicker3.join()
# press `F1` to exit
if key == keyboard.Key.f1:
return False
# --- main ---
running = False # default value at start
def main(*args, **kwargs):
asyncio.run(on_press(args[0]))
try:
print("Starting program")
print("- press E to start/stop thread")
print("- press F1 to exit")
print("- press Ctrl+C to exit")
lis = keyboard.Listener(on_press=main)
lis.start()
print("Listening ...")
lis.join()
print("Exiting program")
except KeyboardInterrupt:
print("Stoped by Ctrl+C")
else:
print("Stoped by F1")
finally:
if running:
running = False
#clicker.join()
#clicker2.join()
#clicker3.join()
I am aware of the .after method, but it requires a function to use.
I tried making a function that does nothing, but it just freezes the screen.
Is there a way to make it so it doens't modify the gui when doing .after? (I tried with a function that did, and it worked)
def doNothing():
return "nothing"
def init_timer(time=25):
global minutes
global onBreak
minutes = 0
onBreak = False
while True:
pomodoro()
def pomodoro():
global pomodoros
if pomodoros < 4:
setTimer(25)
while not(isTimerDone):
print("Timer In Progress")
setTimer(5)
while not(isTimerDone):
pomodoros += 1
else:
setTimer(30)
def timerDone():
global onBreak
global isTimerDone
isTimerDone = True
reminderTitle.config(text="The timer is done!")
onBreak = not(onBreak)
if onBreak:
reminderTitle.config(text="Go on break!")
else:
reminderTitle.config(text="Get to work!")
timer.config(text="Completed")
playsound(f'{os.getcwd()}/Audio/notification.mp3')
def setTimer(mins=25):
global isTimerDone
isTimerDone = False
timer.config(text="In Progress")
window.after(mins * 60 * 1000, timerDone)
This problem occurs when you use while function . So, in order to make your program work properly you have to use .after only , not inside a while function .Here is an example that you could base on to improve your program :
import tkinter as tk
root = tk.Tk()
clock = tk.Label(root)
k = 0
def timing(time):
'''time in minutes'''
global k
k = time
clock.configure(text = 'you still have : ' + str(time) + ' minutes')
def change_value():
global k
if k > 0:
k = k-1
clock.configure(text = 'you still have : ' + str(k)+' minutes')
root.after(60000,change_value)
else :
clock.configure(text = "it's over")
root.after(60000,change_value)
timing(5)
clock.pack()
root.mainloop()
I have a python script that prints a spinner. This spinner, hopefully, will last until stopped.
spinnerFrames = [
"/",
"-",
"\\",
"|",
]
def spinner():
i = 0
while True:
clearScreen() #function to clear the screen
print(spinnerFrames[i])
i = i + 1
if (i == 3):
i = 0
sleep(0.15)
spinner()
sleep(3)
# break out here
print("Done!")
I know you can do sys.stdout.write() and then only delete that line, but that's beside the point.
I can't figure out the best way to stop the loop and exit the function. (To continue on in my code)I'd like to be able to break from the loop down where you call it, as I hope to make this a Pip package.
This, I assume is possible, though I don't know how to do it. Thanks for your help!
You need to run it asynchronously, like how the multiprocessing library allows you to do. When you create a separate thread, you'll be left with a handle on it that you can use to kill it when you want it to stop.
from multiprocessing import Process
from time import sleep
spinnerFrames = [
"/",
"-",
"\\",
"|",
]
def spinner():
i = 0
while True:
print(spinnerFrames[i], end='\r')
i = i + 1
if (i == 3):
i = 0
sleep(0.15)
if __name__ == '__main__':
p = Process(target=spinner)
p.start()
sleep(3)
p.terminate()
print("Done!")
Here is a reference implementation from one of my projects. It prints dots instead of a spinner, but it is trivial to change:
import threading
import time
def indicate_wait(func):
active = threading.Lock()
def dot_printer():
while active.locked():
print('.', end='', flush=True)
time.sleep(1)
def wrapper(*args, **kwargs):
t = threading.Thread(target=dot_printer)
active.acquire()
t.start()
res = func(*args, **kwargs)
active.release()
return res
return wrapper
Example:
#indicate_wait
def test():
time.sleep(5)
record when it started, then break loop if current time - start time >
duration.
import time
spinnerFrames = [
"/",
"-",
"\\",
"|",
]
def spinner():
i = 0
startTime = time.time()# record starting time
duration = 3
while True:
clearScreen() #function to clear the screen
print(spinnerFrames[i])
i = i + 1
if (i == 3):
i = 0
if time.time() - startTime > duration:
break
sleep(0.15)
spinner()
print("Done!")
I want to run a program that can ask for input and run threads at the same time.
For example:
import threading
def get_input():
while True:
var = input('prompt> ')
do_stuff
#main loop
while True:
input_thread = threading.Thread(target=get_input)
input_thread.start()
do_stuff_that_doesn't_work
So the problem above would be that it asks for input(prompt>) and while it's asking for input, do_stuff_that_doesn't_work won't work.
I've seen people get by this before but I don't know how to do it.
You shouldn't be creating a thread inside your while loop. Try this code...
import threading
import time
run = True
def get_input():
global run
while run:
var = input('prompt> ') #python 3 only
print('Input was ', var)
if 'q' == var:
run = False
input_thread = threading.Thread(target=get_input)
input_thread.start()
print('Type q to exit')
ctr = 0
while run:
ctr += 1
time.sleep(0.1)
print('Exiting with ctr: ', ctr)
I'm writing a code that basically runs without a loop for the sake of mobility and functionality. Let's say that when I run the program I use the -i option to continue using the python interpreter as it loads every function written. The thing is that I'm using a screensaver like function after the program print some basic information to make it look not so boring.
My question is: How can I maintain the screen saver running without blocking the interpreter prompt. I already wrote how to handle keyboard input to stop it using curses "getch()". I tried using threading but with no avail as it doesn't detect any keyboard input so it keeps running.
Is there any way I can get around this? How can I detect any input without blocking therefore retaining the interpreter prompt?
Right know it detects an input and raise a KeyboardException captured to make the screensaver stop.
Thanks in advance
I'm using this code with some added modifications:
Matrix-Curses
What I have so far:
Completed Code
This are the modifications done to the code:
def clear(int=None):
""" Clear Terminal Screen """
from subprocess import call
call('clear')
if int == 0:
exit()
def Matrix():
steps = 0
global scr
curses.curs_set(0)
curses.noecho()
if USE_COLORS:
curses.start_color()
curses.use_default_colors()
curses.init_pair(COLOR_CHAR_NORMAL, curses.COLOR_GREEN, curses.COLOR_BLACK)
curses.init_pair(COLOR_CHAR_HIGHLIGHT, curses.COLOR_WHITE, curses.COLOR_GREEN)
curses.init_pair(COLOR_WINDOW, curses.COLOR_GREEN, curses.COLOR_GREEN)
height, width = scr.getmaxyx()
window_animation = None
lines = []
for i in range(DROPPING_CHARS):
l = FallingChar(width, MIN_SPEED, MAX_SPEED)
l.y = randint(0, height-2)
lines.append(l)
scr.refresh()
while True:
height, width = scr.getmaxyx()
for line in lines:
line.tick(scr, steps)
for i in range(RANDOM_CLEANUP):
x = randint(0, width-1)
y = randint(0, height-1)
scr.addstr(y, x, ' ')
if randint(0, WINDOW_CHANCE) == 1:
if window_animation is None:
#start window animation
line = random.choice(lines)
window_animation = WindowAnimation(line.x, line.y)
if not window_animation is None:
still_active = window_animation.tick(scr, steps)
if not still_active:
window_animation = None
scr.refresh()
time.sleep(SLEEP_MILLIS)
if SCREENSAVER_MODE:
key_pressed = scr.getch() != -1
if key_pressed:
raise KeyboardInterrupt
steps += 1
def ScreenSaver():
from time import sleep
from datetime import datetime as dt
global scr
TimeLimit = 10
StartTime = dt.now()
while True:
try:
sleep(1)
StopTime = (dt.now() - StartTime)
LastTime = StopTime.days*86400000 + StopTime.seconds*1000 + StopTime.microseconds/1000
if LastTime >= TimeLimit:
GetLocaleStatus = locale.getlocale()
locale.setlocale(locale.LC_ALL, '')
scr = curses.initscr()
scr.nodelay(1)
key_being_pressed = scr.getch() != -1
if not key_being_pressed:
try:
Matrix()
except KeyboardInterrupt:
TimeLimit = 30000
StartTime = dt.now()
raise KeyboardInterrupt
except KeyboardInterrupt:
curses.endwin()
curses.curs_set(1)
curses.reset_shell_mode()
curses.echo()
clear()
# return
main()