1

Simple code, does not work, is there anything else I need to do? This is just a test, I just want to know if 'volumemute' works or not, other special keys like 'capslock', and 'volumeup' do not work as well. What is 'volumemute' doing? is it muting the system? was hoping to see mac's little volume window, but it also does not mute, say, a youtube video on firefox...

import pyautogui
import time

confirm_window = pyautogui.alert()
if confirm_window == 'OK':
    time.sleep(1)
    pyautogui.press('volumemute')       # Does not work
    pyautogui.press('a')                # Does work
    pyautogui.press('b')                # Does work

I have tried the solution on this link, If I copy either Phylliida's solution or kenorb's solution on a new file and call KeyPress() of the same examples, the same result happens.

I also saw on pyautogui's github page that there is a permission issue with mojave, and even though it should not affect me I added PyCharm, Python Launcher and Terminal to the list in Accessibility, image, I want to be able to lower the volume in my script when I press a button that performs other actions as well, like moving the cursor to a specific coordinate etc. Also, Macbook early 2011, high sierra is as far as I can upgrade de OS

Many thanks

ArtDa
  • 13
  • 7

1 Answers1

1

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.

Asmus
  • 5,117
  • 1
  • 16
  • 21
  • Wow that was impressive and fast. Thank you so much for such a clear explanation and specially for the hand holding, really, I followed the steps as they where posted and edited the code in _pyautogui_osx.py, with the provided code and that was it, it worked! I did have to change my script from pyautogui.press('volumemute') to pyautogui.press(u'KEYTYPE_MUTE') like yo said to do at the end of the instructions. Thank you for taking the time to fix this. – ArtDa Nov 04 '20 at 03:38
  • We wrote a script as a part of our packaging workflow to apply this hack on the fly https://github.com/shubham1172/remote-play/blob/main/hack/fix_pyautogui_macos.py – Shubham Sharma May 17 '21 at 12:25