PyAutoGUI - Cross-Platform Automation Module
PyAutoGUI is a Python module for automating tasks on Windows, Linux and MacOS. "To automate" is generally understood as controlling the mouse and keyboard, although in this particular case other tools are included, such as dialogs and screenshots.
The module API is quite simple, as we'll see. Unfortunately, PyAutoGUI functions do not follow the naming convention recommended by the PEP 8 – Style Guide for Python Code.
Installing PyAutoGUI¶
PyAutoGUI can be installed along with all its dependencies via pip. Open a terminal and run:
pip install pyautogui
If you have problems installing with pip, just download the source code, unzip and run:
python setup.py install
In order to successfully run PyAutoGUI on Linux, the following dependencies must also be installed:
pip install python3-xlib sudo apt-get install scrot sudo apt-get install python3-tk sudo apt-get install python3-dev
On Max OS the following is required:
pip install pyobjc-core pip install pyobjc
On Windows the package does not require any additional installation.
Mouse Automation¶
To get mouse position:
>>> import pyautogui >>> pyautogui.position() Point(x=913, y=444)
To move the mouse to a certain position:
>>> pyautogui.moveTo(300, 200)
The code places the cursor at position X=300 Y=200, with the origin of coordinates being the upper left corner.
By default the transition occurs instantly. By passing the duration
parameter you can tell the module that the movement should take a certain number of seconds.
# Take 3 seconds to move the mouse. >>> pyautogui.moveTo(300, 200, 3)
You can also configure how the transition from the current position to the target position should be made, which by default occurs linearly, via a fourth parameter called tween
. The options are:
linear
(default value)easeInBack
easeInBounce
easeInCirc
easeInCubic
easeInElastic
easeInExpo
easeInOutBack
easeInOutBounce
easeInOutCirc
easeInOutCubic
easeInOutElastic
easeInOutExpo
easeInOutQuad
easeInOutQuart
easeInOutQuint
easeInOutSine
easeInQuad
easeInQueart
easeInQuint
easeInSine
easeOutBack
easeOutBounce
easeOutCirc
easeOutCubic
easeOutElastic
easeOutExpo
easeOutQuad
easeOutQueart
easeOutQuint
easeOutSine
For example:
>>> pyautogui.moveTo(300, 200, 3, pyautogui.easeInBack)
The moveRel()
function is similar to the previous one, but the X and Y values are specified relative to the current cursor position, so negative values can also be used.
# Move the mouse up and to the right. >>> pyautogui.moveRel(50, -100, 1)
To simulate a mouse click:
>>> pyautogui.click() >>> pyautogui.doubleClick() >>> pyautogui.tripleClick()
These three functions simulate a left click by default. To change this, specify the button
parameter, which can take left
(default), middle
or right
.
# Double left click. >>> pyautogui.doubleClick(button="right")
You can also specify where the click should be done within the screen:
# Click at X=50, Y=100 >>> pyautogui.click(50, 100)
A click is simulated by generating a mouse-down and a mouse-up event. These events can also be generated individually:
# Simulate pyautogui.click(). >>> pyautogui.mouseDown() >>> pyautogui.mouseUp()
To drag and drop:
>>> pyautogui.dragTo(500, 400)
By default the mouse is dragged by holding down the right button. dragTo()
accepts the same parameters as click()
.
It is generally recommended that the operation does not occur immediately so that it works correctly on all platforms:
# Recommended. >>> pyautogui.dragTo(500, 400, duration=0.3)
To specify the position in relative terms, use dragRel()
:
>>> pyautogui.dragRel(100, 50)
The drag and drop method is basically similar to the following, as long as the duration
parameter is not specified:
pyautogui.mouseDown() pyautogui.moveTo(x, y) pyautogui.mouseUp()
To scroll up or down:
# Scroll up. >>> pyautogui.scroll(400) # Scroll down. >>> pyautogui.scroll(-400)
The meaning of the argument is highly platform dependent, so I recommend trying out some arbitrary numbers to see which one suits your needs.
Keyboard Automation¶
To press and release a key:
pyautogui.press("a") pyautogui.press("enter")
To write text:
pyautogui.typewrite("Python Assets") # "\n" causes the Enter key to be pressed. pyautogui.typewrite("Python\nAssets")
To perform key combinations:
# CTRL + F5. pyautogui.hotkey("ctrl", "f5")
We can see a list of available keys via:
>>> pyautogui.KEYBOARD_KEYS
Both typewrite()
and hotkey()
accept interval
to specify the interval (in seconds) between one key and another.
pyautogui.typewrite("Python Assets", interval=0.2)
Message Boxes and Dialogs¶
PyAutoGUI includes the PyMsgBox module, which allows you to create message boxes and dialogs by internally using Tk.
# Display a message. pyautogui.alert("Hello world!", "From PyAutoGUI")
The alert()
function displays a message on the screen with a title, and returns the text of the pressed button ("OK"
by default) or None
if the window was closed. To change the button text, pass a third argument.
pyautogui.alert("Hello world!", "From PyAutoGUI", button="OK")
If you want the message to show several options, use confirm()
:
# Buttons. OPT_CLOSE = "Yes, close" OPT_SAVE_AND_CLOSE = "Save All and Close" OPT_KEEP_WORKING = "No, keep working" # Create the message. opt = pyautogui.confirm( "Do you want to close the program?", "Confirmation", [OPT_CLOSE, OPT_SAVE_AND_CLOSE, OPT_KEEP_WORKING] ) # Make decision based on button pressed. if opt == OPT_CLOSE: # ... elif opt == OPT_SAVE_AND_CLOSE: # ... elif opt == OPT_KEEP_WORKING: # ...
To request the user to enter a text, there is a prompt()
function.
# The function returns None if the window was closed or "Cancel" was pressed. user = pyautogui.prompt("Enter your username", "Login")
It is possible to pass a default value and a timeout in milliseconds:
# Default value "user1" and close after 5 seconds. user = pyautogui.prompt("Enter your username", "Login", default="user1", timeout=5000)
Screenshots¶
To take a screenshot:
>>> screenshot = pyautogui.screenshot()
Since PyAutoGUI works internally with PIL/Pillow, screenshot
will be an instance of PIL.Image.Image
. Thus you can use screenshot.save("output.png")
to save the image or screenshow.show()
to visualize it.
Capture a portion of the screen:
>>> screenshot = pyautogui.screenshot(region=(50, 50, 400, 300))
region
must be a (X, Y, Width, Height)
tuple.
To get the color of a pixel as a RGB tuple:
# Get pixel color at X=500, Y=400 >>> screenshot.getpixel((500, 400)) (225, 228, 229)
To find out if a pixel equals a certain color, you can use:
>>> pyautogui.pixelMatchesColor(500, 400, (225, 228, 229)) True
Although this code is similar to screenshot.getpixel((500, 400)) == (225, 228, 229)
, pixelMatchesColor()
accepts an extra argument called tolerance
that controls how much you can vary the color to make the search less restrictive.
# The color does not match exactly but it is close. >>> pyautogui.pixelMatchesColor(500, 400, (220, 230, 232), tolerance=10) True
Locate an image within the screen:
# Returns a (X, Y, Width, Height) tuple if image.png # is found on screen. >>> pyautogui.locateOnScreen("image.png") (759, 44, 96, 48)
The function also accepts images opened by Pillow:
>>> from PIL import Image >>> image = Image.open("image.png") >>> pyautogui.locateOnScreen(image) (759, 44, 96, 48)
If the image appears multiple times on the screen, locateAllOnScreen()
returns an iterator with every match:
>>> list(pyautogui.locateAllOnScreen("image2.png")) [(1060, 629, 17, 20), (1177, 629, 17, 20)]
Locate an image within a region of the screen:
# Also applies to locateAllOnScreen(). >>> pyautogui.locateOnScreen("image.png", region=(0, 0, 1100, 300)) (759, 44, 96, 48)
Specifying a region greatly increases the performance of the function.
Locate an image considering only grayscale:
# Also applicable to locateAllOnScreen(). >>> pyautogui.locateOnScreen("image.png", grayscale=True) (759, 44, 96, 48)
grayscale=True
has a ~30% performance speedup.
Miscellaneous¶
To get the size of the screen:
>>> pyautogui.size() Size(width=1360, height=768)
Determine if a pair of coordinates are within the screen limits:
>>> pyautogui.onScreen(100, 500) True >>> pyautogui.onScreen(1400, 700) False