Странное смешивание системы + homebrew Python с LLDB

Когда я пытаюсь запустить интерпретатор Python в lldb, я вижу:

$ 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.

Когда я проверяю, какая версия Python была запущена, Python сообщает, что это должен быть Python Homebrew (который символически привязан к этому месту):

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

Однако, спрашивая версию Python, возвращается версия, связанная с установкой Python по умолчанию, например.

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

И, просто чтобы подтвердить, версия Python на двоичном пути выше действительно отличается (обратите внимание на разницу в микро версии):

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

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

Чтобы сделать вещи более запутанными, имя _remove_dead_weakref существует в модуле _weakref для моей установки на Homebrew Python, но не для установки по умолчанию:

$ /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>

Любая идея, что могло бы вызвать этот очевидный перекрестный разговор между моими установками Python с LLDB? Как я могу предотвратить это?

Ответ 1

Обходной путь к этой проблеме заключается в явном запуске LLDB только с установкой системы Python на PATH, например

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

Кажется, что LLDB запрашивает PATH для "активной" установки Python; если у вас есть домашняя установка Python, доступная на PATH, тогда вы можете запустить такой перекрестный разговор, когда LLDB пытается запустить Python.

Ответ 2

Если мы запустим lldb с установленным DYLD_PRINT_LIBRARIES=1, то увидим, что он загружает Python.framework из /System/Library, а затем некоторые другие библиотеки Python из Homebrew:

dyld: loaded: /System/Library/Frameworks/Python.framework/Versions/2.7/Python
...
dyld: loaded: /usr/local/Cellar/[email protected]/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload/_locale.so

Но если мы скажем DYLD специально загружать Python.framework из Homebrew, то это сработает:

DYLD_FRAMEWORK_PATH="$(brew --prefix [email protected])/Frameworks/" "$(xcrun -f lldb)"

Протестировано на macOS 10.13.6 с brew'd Python 2.7.15.

Обновление: Когда защита целостности системы включена, использование DYLD_FRAMEWORK_PATH может быть запрещено в исполняемых батутах инструментов командной строки Xcode, запущенных из /usr/bin. Чтобы обойти это, мы запускаем xcrun -f lldb, чтобы использовать настоящий исполняемый файл LLDB.

Ответ 3

Вы можете просто запустить brew unlink [email protected] вместо его удаления. Это удалит Homebrew Python 2.x из вашей PATH. Многие формулы Homebrew зависят от Homebrew Python 2.x, поэтому вы можете сохранить установленный brew Python 2.x, исправляя при этом ошибку с помощью lldb.

Если вы управляете настройкой Homebrew с помощью Homebrew Bundle, вы можете добавить эту строку в свой Brewfile:

brew "[email protected]", link: false