Ah well, that took a bit to figure out. :-)
Finding the bug:
Turns out that one of the many issues with pyautogui is this one from 2015 complaining that press is not working for all keys in macOS, which already has a partial (!!) solution proposed in pull #213. In this specific case, the original code is using two consecutive if …
statements instead of if … elif …
which makes the code break.
If you examine the code on GitHub, you'll find that the .press()
method is defined in init.py to refer to the platform-dependent _keyup()
and _keydown()
function calls defined here for macOS. If you manually apply the fix from pull #213, you'll still have to fix another thing, however:
Pyautogui uses (both in _keyup()
as well in _keydown()
) the line:
if key in special_key_translate_table:
but before this line is executed, "key
" has already been transformed to lowercase due this line in init.py:
if len(key) > 1:
key = key.lower()
The dictionary for special_key_translate_table
defined here however expects uppercase keys like "KEYTYPE_MUTE
" so the lookup won't work!
Fixing the code:
First, figure out where the pyautogui code lives on your installation (i.e. figure out where the site-packages are installed). The easiest way to do this is run this code:
from pyautogui import press
press()
which should throw an error message like this:
Traceback (most recent call last):
File "pyautogui_test_2.py", line 6, in <module>
press()
File "/path/to/the/python/site-packages/pyautogui/__init__.py", line 586, in wrapper
returnVal = wrappedFunction(*args, **kwargs)
TypeError: press() missing 1 required positional argument: 'keys'
Note that the path within the Traceback is dependent on your installation, and now go and open the pyautogui folder within your site-packages (i.e. "/path/to/the/python/site-packages/pyautogui/") and therein edit the file "_pyautogui_osx.py" near line 219 to this:
def _keyDown(key):
if key.upper() in special_key_translate_table:
_specialKeyEvent(key.upper(), 'down')
elif key not in keyboardMapping or keyboardMapping[key] is None:
return
else:
_normalKeyEvent(key, 'down')
def _keyUp(key):
if key.upper() in special_key_translate_table:
_specialKeyEvent(key.upper(), 'up')
elif key not in keyboardMapping or keyboardMapping[key] is None:
return
else:
_normalKeyEvent(key, 'up')
which contains both the fix from pull #213 mentioned above, as well as a corrected lookup function using key.upper()
. Now you should be able to use all the keys from the aforementioned special_key_translate_table
dictionary to e.g. mute the system volume by calling press(u'KEYTYPE_MUTE')
in your scripts.
Note that all special keycodes are also defined on Apple's opensource documentation for the Human Interface system.