Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange mixing of system + homebrew Python with LLDB

When I attempt to run the Python interpretter within lldb, I'm seeing:

$ lldb
(lldb) script
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/usr/local/Cellar/python/2.7.14/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.py", line 52, in <module>
    import weakref
  File "/usr/local/Cellar/python/2.7.14/Frameworks/Python.framework/Versions/2.7/lib/python2.7/weakref.py", line 14, in <module>
    from _weakref import (
ImportError: cannot import name _remove_dead_weakref
Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.

When I inspect what version of Python was launched, Python reports that it should be the Homebrew Python (which is symlinked into this location):

>>> sys.executable
'/usr/local/opt/python/bin/python2.7'

However, asking the Python version returns the version associated with the default system Python installation, e.g.

>>> sys.version_info
sys.version_info(major=2, minor=7, micro=10, releaselevel='final', serial=0)

And, just to confirm, the Python version at the binary path above is indeed different (note the difference in the micro version):

$ /usr/local/opt/python/bin/python2.7 --version
Python 2.7.14

$ /usr/bin/python --version
Python 2.7.10

To make things more confusing, the name _remove_dead_weakref does exist in the _weakref module for my Homebrew Python installation, but not the default system installation:

$ /usr/bin/python -c "import _weakref; print _weakref._remove_dead_weakref"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AttributeError: 'module' object has no attribute '_remove_dead_weakref'

$ /usr/local/opt/python/bin/python2.7 -c "import _weakref; print _weakref._remove_dead_weakref"
<built-in function _remove_dead_weakref>

Any idea what could be causing this apparent cross-talk between my Python installations with LLDB? How can I prevent this?

like image 777
Kevin Ushey Avatar asked Dec 05 '17 16:12

Kevin Ushey


3 Answers

One workaround to this issue is to explicitly launch LLDB with only the system Python installation on the PATH, e.g.

PATH=/usr/bin /usr/bin/lldb

It appears as though LLDB queries the PATH for the 'active' Python installation; if you have a Homebrew installation of Python available on the PATH then you can run into this sort of cross-talk when LLDB attempts to launch Python.

like image 178
Kevin Ushey Avatar answered Nov 14 '22 09:11

Kevin Ushey


If we run lldb with DYLD_PRINT_LIBRARIES=1 set, then we can see that it's loading the Python.framework from /System/Library, but then some other Python libraries from Homebrew:

dyld: loaded: /System/Library/Frameworks/Python.framework/Versions/2.7/Python
...
dyld: loaded: /usr/local/Cellar/python@2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload/_locale.so

But if we tell DYLD to specifically load Python.framework from Homebrew, then it works:

DYLD_FRAMEWORK_PATH="$(brew --prefix python@2)/Frameworks/" "$(xcrun -f lldb)"

Tested on macOS 10.13.6 with brew'd Python 2.7.15.

Update: When System Integrity Protection is enabled, using DYLD_FRAMEWORK_PATH may be prohibited on the Xcode Command Line Tools trampoline executables running from /usr/bin. To work around that, we run xcrun -f lldb to use the real LLDB executable instead.

like image 7
rgov Avatar answered Nov 14 '22 09:11

rgov


You can simply run brew unlink python@2 instead of uninstalling it. This will remove Homebrew's Python 2.x from your PATH. A lot of Homebrew formulas depend on Homebrew's Python 2.x, so you can keep the brew-installed Python 2.x while also fixing the error with lldb.

If you manage your Homebrew setup with Homebrew Bundle, you can add this line to your Brewfile:

brew "python@2", link: false
like image 4
rootbeersoup Avatar answered Nov 14 '22 11:11

rootbeersoup