ModuleNotFoundError 即使模块在 sys.path

ModuleNotFoundError even though module is in sys.path

我对这里明显的不一致感到困惑。它与 setproctitle 模块有关。基本上python3.6可以看到,python3.8看不到。

我可以用几个简单的命令行演示来演示 运行:

python3.6 -c "import sys; print(sys.path); import setproctitle; print(setproctitle.__file__)"

python3.8 -c "import sys; print(sys.path); import setproctitle; print(setproctitle.__file__)"

这里是比较:

$ python3.6 -c "import sys; print(sys.path); import setproctitle; print(setproctitle.__file__)"
['', '/usr/lib/python36.zip', '/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload', '/home/bernd/.local/lib/python3.6/site-packages', '/usr/local/lib/python3.6/dist-packages', '/usr/lib/python3/dist-packages', '/usr/lib/python3.6/dist-packages']
/usr/lib/python3/dist-packages/setproctitle.cpython-36m-x86_64-linux-gnu.so
$ python3.8 -c "import sys; print(sys.path); import setproctitle; print(setproctitle.__file__)"
['', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '/home/bernd/.local/lib/python3.8/site-packages', '/usr/local/lib/python3.8/dist-packages', '/usr/lib/python3/dist-packages']
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'setproctitle'

值得注意的是,对于 Python3.6 和 Python3.8,setproctitle 位于 /usr/lib/python3/dist-packages 中,而该目录位于 sys.path 中。

我们可以从中得出什么结论?

鉴于名为 /usr/lib/python3/dist-packages/setproctitle.cpython-36m-x86_64-linux-gnu.so 的加载文件的名称中有一个可疑的 36m,这表明 Python3.8 可能正在寻找 /usr/lib/python3/dist-packages/setproctitle.cpython-38m-x86_64-linux-gnu.so,但这会引发辅助问题:我们如何(规范地)获得 setproctitle 的 3.8 包?

我承认我偷偷试过了:

sudo ln /usr/lib/python3/dist-packages/setproctitle.cpython-36m-x86_64-linux-gnu.so /usr/lib/python3/dist-packages/setproctitle.cpython-38m-x86_64-linux-gnu.so

并再次尝试,但不仅仅是名称。我曾尝试在网上查找相关信息,但到目前为止什么也没找到,有点卡住了。如果有一些关于这里发生的事情以及如何为不同 Python 版本并排放置看似二进制库的简单摘要,我将很高兴得到指点。

我的猜测是:

  1. .so 文件是一个二进制文件,其中包含指向特定 Python 版本的链接
  2. 因此需要为 Python3.8
  3. 重建
  4. 可能是,考虑到Python3.8还很年轻,还没有重建分发
  5. 也许可以即时重建它,如果有新的语法,也许可以使用 apt。

您有一个 extension module,它是使用 CPython 3.6 / Linux 运行时构建和标记的。 简单地重命名该文件不是一个好主意,也不太可能奏效。即使该文件存在于 sys.path 上,它也会被 Python 3.8 运行时忽略,因为标签不匹配。

PEP 3149 -- ABI version tagged .so files

要获得 3.8 版本,您应该使用 3.8 运行时构建(即从源代码安装):

python3.8 -m pip install setproctitle