What I want to achieve here is that when I press * the program should wait for 17 seconds before doing anything else and if I don't press anything it can continue pressing the ] key every 11 seconds. The problem here is that if I were to press the * while we are in any time.sleep period, the press of the key will not go through.
import pyautogui
import time
import keyboard
while not keyboard.is_pressed('*'):
if keyboard.is_pressed('*'):
time.sleep(17)
else:
time.sleep(11)
pyautogui.press(']')
There are a lot of ways to accomplish this.
One of the simpler (but certainly not best) ways is to sleep in shorter increments (say 0.1 sec) to wake up periodically and poll the keyboard. You would track in a variable the system time at which point you are done "waiting" and break out of your loop at that point.
This works for me
import pyautogui
import time
import keyboard
last_star_press = 0 # initialize variable to keep track of time of last * press
while True:
if keyboard.is_pressed('*'):
last_star_press = time.time() # update time of last * press
time.sleep(17)
else:
if time.time() - last_star_press >= 11:
pyautogui.press(']')
last_star_press = time.time() # update time of last key press
time.sleep(1) # add a small delay to reduce CPU usage
Related
I have an infinite while loop running until I hit a key to exit it. Currently, I have an if statement that toggles a boolean if I press a key.
if keyboard.is_pressed('s'):
armed = not armed
When I run the loop and press the key, sometimes it activates twice because the key was down long enough during the press to be activated in the next iteration of the while loop.
Are there any solutions that don't involve putting a delay in the while loop? It is a cv2 based script so any delays will result in an fps drop of the video being captured.
You could keep track of the time you detect the press. Anything within a time interval from there is ignored.
import time
last_press = time.time()
key_delay_seconds = 1.0
armed = False
while True:
if keyboard.is_pressed('s'):
if cur_time := time.time() > last_press + key_delay_seconds:
armed = not armed
last_press = cur_time
print(armed)
I wanted to make a simple macro to hold down 'W' for some time, but even simple script like this does not work.
import time
import pyautogui
from pynput.keyboard import Key, Controller
keyboard = Controller()
pyautogui.keyDown('w')
time.sleep(3)
pyautogui.keyUp('w')
time.sleep(5)
keyboard.press('w')
time.sleep(3)
keyboard.release('w')
If i test it in any text editor/text input window it will write one 'w' when script starts and anouther one after 8 seconds without holding/spaming it. And therefore it DOES NOT work in any games what should be the whole purpose of this script. I tried it in a huge variety of different games (Java Minecraft, source Gmod, Roblox and some unity games) and this script just was not working in any of them, but if a game has chat, search box or any other text input window, this script will write one 'w' and anouther one after some time in it.
I realy have no idea why this is happening, but i remembered that two years ago i tried to make similar script on pynput and it did work, so i tried installing old versions of pynput, but that did not help me as well...
So after a long time i could finaly take care of the issue, and i figured out that the source of the problem was in the Microsoft's DirectInput. Basically pynput and pyAutoGUI are not able to get in to DirectInput and there is no signal at all while I thought that there wwas a signal, but for so little amount of time that the games just were not able to pick it up. And the solution to this was pretty easy thanks to this guy PyAutoGUI not working? Use DirectInput. Thanks to his PyDirectInput librarry you are able to use python to emulate button presses and holdes in games!
This might be a start to work with:
#https://stackoverflow.com/questions/66284097/pynput-and-pyautogui-cant-hold-keys
#simulate keystroke for some amount of time
import msvcrt
import time
def press(char, duration, sleep, limit=None):
while True:
lim = limit
t1 = time.time()
while time.time() - t1 < duration: # do for duration specified
msvcrt.putch(char) # output character, putch() awaits a byte string
if lim: # limit specified?
lim -= 1
if lim == 0: # limit reached
break
time.sleep(SLEEP)
if msvcrt.kbhit(): # key pressed?
char = msvcrt.getch()
press(b'w', .001, 2, None)
This is my code
It performs keep_click_attendance_link() enter code here function until JustBefore time is reached
and then at EndTime it performs the leave_the_meeting() function
import pyautogui
import time
import pause
import datetime
import schedule
YEAR = 2020
MONTH = 11
DATE = 6
HOUR = 13
MINUTES = 3
SECONDS = 15
now = datetime.datetime.now()
EndTime = now.replace(hour=HOUR, minute=MINUTES, second=SECONDS, microsecond=0)
JustBefore= now.replace(hour=HOUR, minute=MINUTES-1, second=SECONDS, microsecond=0)
def leave_the_meeting():
pyautogui.click(1198, 1072)
time.sleep(3)
pyautogui.click(1443, 998)
time.sleep(1)
pyautogui.click(1398, 933)
def click_attendance_link():
pyautogui.click(1665, 674)
time.sleep(9)
def keep_click_attendance_link():
while datetime.datetime.now() < JustBefore:
click_attendance_link()
# Sleep for 60 secs before trying again
time.sleep(9)
keep_click_attendance_link()
while datetime.datetime.now() < EndTime:
# Sleep for 1 sec intervals:
time.sleep(1)
# eventually Leave the meeting at Endtime
leave_the_meeting()
So what I want is it to stop the function keep_click_attendance_link() when the attendance link is clicked. The teacher sends the link at any random time, so I had to program it to continuously click at that spot until 1 minute before the EndTime which is JustBefore. The meeting is on zoom client not on the web browser.
First of all, don't skip lesson.
Secondly, to do what you intend to do, for educational purpose only, you will need a mechanism to detect whether the button has appeared yet. Since you can't directly communicate with the zoom client, you will need to detect pixel by pixel in the screen and analyze whether the color of that pixel/area is the color for the attendance button.
To do that, you will need to find the color code for your button first. It can be simply done by screen capture and put that in any image processing software, even Paint. After you have your color, you can use Pillow module to analyze that particular spot, more on that here.
After the checking mechanism is done, you can integrate that into your code and stop the function execution once the button has been detected.
def check_attendance_link_presence():
# check it here
pass
def keep_click_attendance_link():
clicked = False
while datetime.datetime.now() < JustBefore and not clicked:
presence = check_attendance_link_presence()
if presence:
click_attendance_link()
clicked = True
# Sleep for 60 secs before trying again
time.sleep(60)
p.s. I intentionally not to include the code for the presence checking here for the sake of encouraging you to spend time learning it while you are "taking a break" from your lessons.
Maybe: Define a variable something like clicked = False, and in the attendance function set it to True. Then modify the While in the other function with an and clicked == False. So your while cycle only loops till the clicked flag is False, but after it clicked the attendance, it'll change to True, and the cycle stops.
I think it would be more elegant with callbacks tough.
I am trying to automate android game using python but I end up in a situation where I have to keep pressing CTRL key and use mouse wheel to zoom out.
I installed Pynput and tried this command
keyboard.press('a')
time.sleep(3)
keyboard.release('a')
But it doesn't keep pressing a key for 3 seconds but press only once.
Can anyone pls tell me a simple script, where it will keep pressing CTRL key and use mouse wheel to zoom out?
I'm assuming you want the key to be pressed over and over again rather than being held down (which is what I think your code above is doing).
You got two options that I know of. The easiest, by far, is to use floats alongside sleep, and do something like this:
timer = 0
while timer < 3:
time.sleep(0.1)
timer += 0.1
keyboard.press('a')
This will press the 'a' key every 0.1 seconds until 3 seconds is reached.
Otherwise, you could import the 'threading' module which lets you run code in paralel, and therefore run a loop and a timer simultaneously. This is probably a huge can of worms for what you're trying to do. The code below presses the 'a' key as fast as possible until the three second timer ends, it doesn't exit threads or anything though, which is why this is probably a bad approach:
global_timer = 0
def keep_pressing_a():
while global_timer <= 3:
keyboard.press('a')
def count_to_three():
global global_timer
keep_counting = True
while keep_counting:
time.sleep(1)
global_timer += 1
if global_timer >= 3:
keep_counting = False
threading.Thread(target=count_to_three).start()
threading.Thread(target=something).start()
Been using the pyautogui module to do most of my things, but I have come across one problem:
I cannot hold down a key for a certain length of time.
Does anyone know any modules that can do this, or have a solution without downloading any modules?
For example (perfect for me):
I go into word, and run my code. Word should just be receiving (w pressed down), with the w's slowly increasing - (after a while holding adds like 5 a half sec).
You can use the following example:
>>> pyautogui.keyDown('shift') # hold down the shift key
>>> pyautogui.press('left') # press the left arrow key
>>> pyautogui.press('left') # press the left arrow key
>>> pyautogui.press('left') # press the left arrow key
>>> pyautogui.keyUp('shift') # release the shift key
In your case you'd use the keyDown function and a timer or equivelent to trigger keyUp.
You can find more information in regards to using timers here or better yet use Timer from the threading library - especially if you want to the processing to continue.
Example of using threading.Timer below.
def hello():
print("hello, world")
t = Timer(30.0, hello)
t.start() # after 30 seconds, "hello, world" will be printed
In the keyDown documentation one can note the following:
NOTE: For some reason, this does not seem to cause key repeats like
would happen if a keyboard key was held down on a text field.
An alternative to using the keyDown function is to repeat the press function; in cases where keyDown is not satisfying the behaviour required by the developer and/or user.
def hold_key(key, hold_time):
import time, pyautogui
start_time = time.time()
while time.time() - start_time < hold_time:
pyautogui.press(key)
or
import pyautogui
while True:
pyautogui.press('w')
The above code is not tested.