'Why does "import pyautogui" give an error [duplicate]

I dont understand why this gives back an error and i'm really confused.

>>> import pyautogui
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/connorgooch/Library/Python/2.7/lib/python/site-packages/pyautogui/__init__.py", line 249, in <module>
    import mouseinfo
  File "/Library/Python/2.7/site-packages/mouseinfo/__init__.py", line 100, in <module>
    from rubicon.objc import ObjCClass, CGPoint
  File "/Library/Python/2.7/site-packages/rubicon/objc/__init__.py", line 3, in <module>
    from .runtime import (  # noqa: F401
  File "/Library/Python/2.7/site-packages/rubicon/objc/runtime.py", line 785
    self.restype, *self.argtypes = ctypes_for_method_encoding(self.encoding)
                  ^
SyntaxError: invalid syntax

How do I fix this?



Solution 1:[1]

Diagnosis

You're running the library in a version of Python that's too old.

You can tell because assignment of the form ..., *whatever = some_function() became valid only in a relatively recent version of Python.

Prior to that, having a unary * (splat operator) like that on the left side of an assignment was a syntax error.

More specifically, you're using Python 2, which we can tell by both the fact that this feature became available in Python 3.0, and the fact that the traceback has paths like this: /Library/Python/2.7/... (that 2.7 is the Python version).

Solution

Use a newer version of Python.

I can't tell you how to do that because that totally depends on how you're currently running Python.

On some systems, the python command is still Python 2, and you need to call python3 to get Python 3. You might also have a situation where you have separate commands like python27 for Python 2.7, python38 for Python 3.8, and python39 for Python 3.9, but python3 and python point to Python 3.8 instead of either the latest 2 or the latest 3.

Also, on some systems, each Python version is installed in a different directory, and if you specify the right path you don't need to worry about the exact command name.

So if you're calling Python from a shell, you may need to change the PATH or the command or both. If you're calling Python from an IDE, there might be a setting for it. And so on.

Similarly, you might need to actually install a newer version of Python, but the right way to do that depends on your system.

Maybe the package manager provided by your operating system like apt or yum or any number of others, or a third-party package manager like brew or chocolatey, or maybe you're using a tool that manages multiple Python versions. Or maybe you just download it manually from the Python webpage.

Based on your traceback, the fact that some of the paths start with /Library/... suggests that you're on MacOS, which means you can probably just get Python 3 by using the command python3, or changing the path your tool is using to Library/Python/3.? (replace ? with the right minor version). And if you don't already have it installed, you can get it from the Python website or the "homebrew" package manager if you're using that or whatever else works on Mac.

Solution (if you really can't use a newer Python)

You can change the line that's raising the syntax error.

There are many equivalent ways to do this once you understand what's going on.

Here is one pattern which is less readable than most, but which you can use in all cases with no understanding or review or changes:

self.restype, self.argtypes = (lambda r: (r[0], list(r[1:])))(ctypes_for_method_encoding(self.encoding))

Background

In Python, a function can return a tuple or something similar like a list.

This is how returning multiple values is implemented.

In order to make this work on the assignment side, Python can do something called "iterable unpacking": foo, bar = my_function() (this is more generally known by other names too, such as "de-structuring assignment").

(This is also what's happening when you "swap" values: foo, bar = bar, foo is actually semantically equivalent to temp = (bar, foo); foo = temp[0]; bar = temp[1]; del temp. First a tuple is created, and then it goes through de-structuring assignment.)

In Python 3, they added a feature where an assignment with the "splat" operator (*) on one of the values will capture "the rest" of the de-structured values. So if you do temp = (1, 2, 3, 4, 5), then foo, bar, *qux = temp will result in foo = 1, bar = 2, and qux = (3, 4, 5).

But in earlier versions of Python that feature didn't exist.

So the line

self.restype, *self.argtypes = ctypes_for_method_encoding(self.encoding)

is taking the return value from ctypes_for_method_encoding, and assigning the first element of it into self.restype and a tuple holding the rest of the elements from it into self.argtypes.

Solution 2:[2]

First try:-

python -m pip install --upgrade pyautogui

If it does not work, then in File "/Library/Python/2.7/site-packages/rubicon/objc/runtime.py", line 785

self.restype, *self.argtypes = ctypes_for_method_encoding(self.encoding)

Try correcting the syntax because you have a syntax error in this line. You can find the syntax on google.

I think you have an error in the asterisk symbol *. But I am not sure.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 wjandrea