使用psycopg2时出现Symbol not found: _PQbackendPID(M1 Mac)

1.问题背景介绍

  M1芯片的Mac,系统指令集构架为arm64。
  最初使用电脑自带Python3(这里是与Mac系统指令集构架一致的)的 pip 安装了 psycopg2 ,连接 PostgreSQL 数据库正常。但是在后来项目中使用的是 conda 中的 python 环境,执行程序并连接数据库的时候,就会出现Symbol not found: _PQbackendPID的问题。

  在网上找到GitHub的issue 似乎也没有找到好的解决办法。

2.问题进一步发现和解决

  最初并没有意识到这和系统的指令集构架相关。后来由于需要将C++的一些写好的程序编译成动态库文件,并在python中进行调用。python代码在运行到需要使用到C++中的函数时,就会出现如下问题:

Traceback (most recent call last):
  File "/Users/debris/Documents/Job/HA/encryption-cpp/test_encrypt.py", line 6, in <module>
    my_func = CDLL(so_file)
  File "/Users/debris/miniconda3/lib/python3.9/ctypes/__init__.py", line 382, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: dlopen(/Users/debris/Documents/Job/HA/encryption-cpp/encrypt_for_python.so, 0x0006): tried: '/Users/debris/Documents/Job/HA/encryption-cpp/encrypt_for_python.so'
(mach-o file, but is an incompatible architecture (have 'arm64', need 'x86_64')), 
 '/usr/local/lib/encrypt_for_python.so' (no such file), '/usr/lib/encrypt_for_python.so' (no such file)

  报错看起来有点复杂,但是,不难发现有一句很奇怪:(mach-o file, but is an incompatible architecture (have 'arm64', need 'x86_64')),大致意思是构架不兼容的问题。Python代码中使用到的动态库是在我 Mac 本地编译的,使用的指令集构架为 arm64 ,但是这里报错信息为什么提示说已有 arm64 而需要 x86_64 ?动态库确定是 arm64 构架,那么可能就是 Python 的问题。

  接下来就要查看一下使用的 Python 是不是真如我们所想。
  首先,查看在使用的 conda 环境中 Python 的情况,如下:

# 先激活conda环境
conda activate
# 查看可执行文件信息
file $(which python3)
/Users/debris/miniconda3/bin/python3: Mach-O 64-bit executable x86_64

  再查看一下本地的情况:

# 先关闭conda环境
conda deactivate
# 查看可执行文件信息
file $(which python3)       
/opt/homebrew/bin/python3: Mach-O 64-bit executable arm64

  果然,情况,其使用的指令集构架是不一样的。使用的动态库文件和使用的 Python 版本达到兼容状态,也就是对应的指令集构架一致,工作就不会有这种问题。也就是说,有两种解决方案,一是使用 x86_64 指令集构架的工具编译动态库,另一种则是使用 arm64 指令集构架的 Python。
  知道了 conda 环境中的指令集构架与 Mac 本地的不同,那么,很容易联想到,之前出现的 Symbol not found: _PQbackendPID ,可能与这里也有关系。
  重新安装 conda ,这次选择使用 arm64 对应版本,成功解决上述两个问题!✌️
  为什么自己安装的 conda 环境中会是对应 x86_64 指令集构架的呢?似乎之前版本的 Mac (还在使用 Intel 芯片的时候),使用的就是这种构架,但是在之后使用 M1 芯片之后,经历了处理器的变革,就改为 arm64 指令集构架了,因此好多软件,给 Mac 用户提供两个版本。在我安装 conda 环境的时候,我并没有注意到这种情况。
  那么,后续,如果类似情形出现构架不兼容的问题,解决方案应当也类似。