Search code examples
python-3.xdelaypyautogui

pyautogui is delayed in .png searches/ going to next line of code too soon


Okay I've gotten pretty far since I started this but I've been wondering about a few things I'd like to improve on.

So When the dell.com/support pops up it takes about 10 seconds for it to figure out where to click. (Lines 31-35) this ends up being an issue because sometimes the next part of the code starts running.

For example while #drivers and downloads is still being searched for it jumps to (ctrl+f "show all")

What can I do to decrease the delays? without just adding in more time.sleep(x) is there something I can set up for a wait until XYZ

"""
Pip install list:

autogui
pyperclip
pillow
"""

import subprocess
import pyperclip
import re
import os
import pyautogui
import time


SerialNumber = 'wmic bios get serialnumber'
result = subprocess.getoutput(SerialNumber)
SerialResult = (result.strip("SerialNumber"))
print(re.sub("[^a-zA-Z0-9]+", "", SerialResult))
pyperclip.copy(re.sub("[^a-zA-Z0-9]+", "", SerialResult))

os.system("start chrome.exe --new-window dell.com/support")

screenWidth, screenHeight = pyautogui.size() #gets the size of Primary Monitor
currentMouseX, currentMouseY = pyautogui.position() #gets the XY position of mouse
print(" X: ",  currentMouseX, "Y: ", currentMouseY,"\n", "Width:",screenWidth, "Height:", screenHeight)

#searchbar
SearchBarLocation = pyautogui.locateOnScreen('SearchBar.PNG')
pyautogui.moveTo(SearchBarLocation)
time.sleep(3)
pyautogui.click()
pyautogui.hotkey('ctrl', 'v')
pyautogui.press('enter')
print(1)
#drivers and download
time.sleep(1)
pyautogui.hotkey('ctrl', 'f')
pyautogui.write('drivers & downloads')
DriversAndDownloadsLocation = pyautogui.locateOnScreen('DriversAndDownloads.PNG')
time.sleep(3)
pyautogui.moveTo(DriversAndDownloadsLocation)
pyautogui.click()
print(2)
#find drivers
time.sleep(1)
pyautogui.hotkey('ctrl', 'f')
pyautogui.write('Find drivers')
time.sleep(1)
FindDriversLocation = pyautogui.locateOnScreen('FindDrivers.PNG')
time.sleep(3)
pyautogui.moveTo(FindDriversLocation)
pyautogui.click()
print(3)
#show all
time.sleep(1)
pyautogui.hotkey('ctrl', 'f')
pyautogui.write('Show all')
time.sleep(1)
ShowAllLocation = pyautogui.locateOnScreen('ShowAll.png')
time.sleep(3)
pyautogui.moveTo(ShowAllLocation)
pyautogui.click()
print(4)
#Dell Update
time.sleep(1)
pyautogui.hotkey('ctrl', 'f')
pyautogui.write('dell command | update application')
time.sleep(1)
DellUpdateLocation = pyautogui.locateOnScreen('DellUpdate.PNG')
time.sleep(3)
pyautogui.moveTo(DellUpdateLcation)
print(5)
#Download
time.sleep(1)
pyautogui.hotkey('ctrl', 'f')
pyautogui.write('Download')
time.sleep(1)
DownloadLocation = pyautogui.locateOnScreen('Download')
time.sleep(3)
pyautogui.moveTo(DownloadLocation)

Solution

  • There are a few things you can do to make locateOnScreen run quicker. You can designate a region to search in and you can toggle the grayscale flag to be True.

    If SearchBar.png always appears in the same area of the screen, you can use a tool in pyautogui to record the co-ordinates. If you open a python shell and write

    import pyautogui
    pyautogui.mouseInfo()
    

    An application called MouseInfo will open up that will assist in recording the co-ordinates. When designating a region for location onscreen, the format is (left, top, width, height).

    For example, if you knew SearchBar.png was reliably always appearing at 1142, 721 and was 160 pixels wide and 80 pixels high, you could use do this:

    pyautogui.locateOnScreen('SearchBar.png', region=(1142, 721, 160, 80))
    

    Optionally, you can also toggle grayscale onto that call to make it faster.

    pyautogui.locateOnScreen('SearchBar.png', region=(1142, 721, 160, 80), grayscale=True)
    

    If you NEED SearchBar.png to continue your script, and the process breaks without finding it, you can implement a technique called Busy waiting. Basically, keep checking for a condition and do not proceed until it is met. The implementation of that would look something like this:

    timer = 0
    timeout_time = 60
    search_bar_location= pyautogui.locateOnScreen('SearchBar.png')
    while search_bar_location is None:
        if timer > timeout_time:
            print('Could not find the search bar in 60 seconds')
            exit(1)
        time.sleep(1)
        search_bar_location = pyautogui.locateOnScreen('SearchBar.png')
        timer += 1
    # Searchbar is available if the code gets here
    pyautogui.moveTo(search_bar_location)
    
    ...
    

    It's generally good practice to not busy wait forever, that's why I've added the timer variables to exit the script after 60 seconds of busy waiting.