恐怕这些答案都不是我可以接受的。因为这些答案并没有解决问题。他们中的一些人是幸运的,或者误解了,甚至是错误的。因此,我将提供自己的解决方案并详细解释该问题。
dylib 加载无效。客户端不应加载未版本化的 libcrypto dylib,因为它没有稳定的 ABI。
根本原因本身就很清楚了。您的 Python 正试图打开(通过dlopen
)一个名为 的未版本化 OpenSSL 共享库libcrypto
。自 Catalina 以来,出于安全原因,Apple 不允许任何人使用它。所以解决方案很简单。只是使用版本控制 OpenSSL。
我编写了一个名为openlib.py
重现问题的 python 脚本。
import sys
from ctypes.util import find_library
from ctypes import CDLL
name = sys.argv[1]
path = find_library(name)
print(f"path: {path}")
lib = CDLL(path)
我在这里使用系统 Python 进行演示
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.15.7
BuildVersion: 19H15
$ /usr/bin/python3 --version
Python 3.8.2
$ ls -al /usr/lib/ | grep 'libcrypto\|libssl'
.rwxr-xr-x 1.1M root 22 Sep 8:29 libcrypto.0.9.7.dylib
.rwxr-xr-x 1.4M root 22 Sep 8:29 libcrypto.0.9.8.dylib
.rwxr-xr-x 1.5M root 22 Sep 8:29 libcrypto.35.dylib
.rwxr-xr-x 1.5M root 22 Sep 8:29 libcrypto.41.dylib
.rwxr-xr-x 1.5M root 22 Sep 8:29 libcrypto.42.dylib
.rwxr-xr-x 1.5M root 22 Sep 8:29 libcrypto.44.dylib
.rwxr-xr-x 32k root 22 Sep 8:29 libcrypto.dylib
.rwxr-xr-x 212k root 22 Sep 8:29 libssl.0.9.7.dylib
.rwxr-xr-x 335k root 22 Sep 8:30 libssl.0.9.8.dylib
.rwxr-xr-x 330k root 22 Sep 8:28 libssl.35.dylib
.rwxr-xr-x 313k root 22 Sep 8:29 libssl.43.dylib
.rwxr-xr-x 300k root 22 Sep 8:29 libssl.44.dylib
.rwxr-xr-x 294k root 22 Sep 8:29 libssl.46.dylib
.rwxr-xr-x 32k root 22 Sep 8:29 libssl.dylib
$ /usr/bin/python3 openlib.py libcrypto
path: /usr/lib/libcrypto.dylib
Abort trap: 6
$ /usr/bin/python3 openlib.py libcrypto.35
path: /usr/lib/libcrypto.35.dylib
$ /usr/bin/python3 openlib.py libcrypto.44
path: /usr/lib/libcrypto.44.dylib
如你看到的。Pythonlibcrypto
因以下诊断报告的参数而崩溃。看起来很相似,对吧?答对了!
Process: Python [97291]
Path: /Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.8/Resources/Python.app/Contents/MacOS/Python
Identifier: Python
Version: 3.8.2 (3.8.2)
Build Info: python3-73040006000000~117
Code Type: X86-64 (Native)
Parent Process: bash [84388]
Responsible: iTerm2 [7705]
User ID: 501
Date/Time: 2020-12-26 00:28:00.281 +0800
OS Version: Mac OS X 10.15.7 (19H15)
Report Version: 12
Anonymous UUID: 1C43F3DB-1783-4B94-B663-7F7E8D331B56
Time Awake Since Boot: 53000 seconds
System Integrity Protection: enabled
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Application Specific Information:
/usr/lib/libcrypto.dylib
abort() called
Invalid dylib load. Clients should not load the unversioned libcrypto dylib as it does not have a stable ABI.
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libsystem_kernel.dylib 0x00007fff69bba33a __pthread_kill + 10
1 libsystem_pthread.dylib 0x00007fff69c76e60 pthread_kill + 430
2 libsystem_c.dylib 0x00007fff69b41808 abort + 120
3 libcrypto.dylib 0x00007fff6766b7e4 __report_load + 415
基于您的 Python 的路径/usr/local/Cellar/python/3.7.4_1/Frameworks/Python.framework/Versions/3.7/Resources/Python.app/Contents/MacOS/Python
。显然,您的 Python 是由 Homebrew 安装的。我相信 Homebrew Python 3 已与仅桶装 OpenSSL 相关联。所以肯定是一些包使用了未版本化的 OpenSSL。查看文件ctypes/macholib/dyld.py
2。它按指定顺序搜索以下目录中的任何库:
DEFAULT_LIBRARY_FALLBACK = [
os.path.expanduser("~/lib"),
"/usr/local/lib",
"/lib",
"/usr/lib",
]
$ /usr/bin/python3
Python 3.8.2 (default, Nov 4 2020, 21:23:28)
[Clang 12.0.0 (clang-1200.0.32.28)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from ctypes.util import find_library
>>> find_library('libcrypto')
'/usr/lib/libcrypto.dylib'
>>>
因此,简单的解决方法是将版本控制 OpenSSL 链接到主目录中的库路径。
$ pwd
/Users/gasolwu
$ ln -s /usr/lib/libcrypto.44.dylib $HOME/lib/libcrypto.dylib
$ $ ls ~/lib
libcrypto.dylib
在那之后。通过运行提供的脚本来测试打开 OpenSSL openlib.py
。它成功返回库路径而不会崩溃。
$ /usr/bin/python3 openlib.py libcrypto
path: /Users/gasolwu/lib/libcrypto.dylib
我也使用Homebrew Python 3。所以我在几天前修复了它并发送了一个拉取请求。如果你已经升级到最新版本的 Python 并且如果 PR 已经合并并且瓶子已经构建和发布。只需运行命令brew reinstall python@3.9
将是解决问题的最简单方法。
不要通过禁用SIP并使用sudo
覆盖您的系统 OpenSSL 来破坏您的系统。
不要安装浪费磁盘空间的重复库。无需在任何位置安装另一个 OpenSSL。
不要使用DYLD_LIBRARY_PATH
如下环境变量。如果您不将此行添加到 shell 配置中,则每次都必须声明。如果这样做,它将影响您机器上的每个程序。
export DYLD_LIBRARY_PATH=/usr/local/opt/openssl/lib:$DYLD_LIBRARY_PATH
最后。如果您通过更新 python 依赖项解决了问题。你可能很幸运。一些软件包通过寻找版本控制 OpenSSL 解决了这个问题。但很多不是。