很抱歉,这些答案都无法满足我的要求。因为这些答案没有解决问题的根本原因。其中一些是幸运的,或者误解了问题,甚至是错误的。因此,我将提供自己的解决方案,并详细解释问题。
引起问题的根本原因非常明显。您的Python正在尝试打开(通过dlopen)一个名为libcrypto的未版本化的OpenSSL共享库。由于Catalina之后,出于安全原因,苹果不允许任何人使用它。因此,解决方案很简单。只需使用带版本号的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
正如您所看到的,Python 因为参数
libcrypto
崩溃了,以下是诊断报告。看起来很相似,对吧?Bingo!
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已经与keg-only 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
之后,请通过运行提供的脚本
openlib.py
来测试打开OpenSSL。它将成功返回库路径,而不会崩溃。
$ /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来修复了这个问题,但是许多软件包没有这样做。