【问题标题】:ModuleNotFoundError even though module is in sys.pathModuleNotFoundError 即使模块在 sys.path
【发布时间】:2019-12-31 07:09:21
【问题描述】:

我对这里明显的不一致感到困惑。它与 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,但这会引发辅助问题:我们如何(规范地)获取3.8 包setproctitle 的?

我承认我偷偷尝试过:

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. 可能是因为 Python3.8 还很年轻,它还没有重新构建以供分发
  4. 也许可以即时重建它,也许使用 apt 如果一种新的语法。

【问题讨论】:

    标签: python-3.x linux python-import .so


    【解决方案1】:

    您有一个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
    

    【讨论】:

    • 效果很好。它安装在~/.local/lib/python3.8/site-packages/setproctitle.cpython-38-x86_64-linux-gnu.so 而不是/usr/lib/python3/dist-packages 我猜这是宜居的,但如果我使用sudo 运行相同的构建,它只会抱怨Requirement already satisfied: setproctitle in /usr/lib/python3/dist-packages 这是一个难题,因为它是正确的,但仅限于3.6 的感觉,所以 3.8 拒绝在那里建造。嗯...
    • 不要使用 sudo 构建。这是各种错误,从来没有理由“sudo pip install”。
    • 真的吗?那么如何为所有依赖 python 3.8 的用户和系统工具提供这样的模块呢?确实,我有一个 Web 服务器,在该服务器上我维护了一个基于 Django 的网站,并且我将专门迁移到 Python 3.8,这样我就可以利用我喜欢的 3.8 功能,那么如何在 Ubuntu 服务器上确保 3.8 版本模块位于系统目录而不是~/.local 目录中?只是好奇。
    • 但是您为什么认为首先需要在系统级别运行?不需要为所有用户安装 Django 应用程序,最佳做法是以普通用户而不是 root 用户身份运行。如果您只想使用特权端口,则可以使用 iptables 或类似的端口转发 80。
    • Web 服务器是一台专用机器。我不知道为什么您认为最新的 Python 版本不应该在系统范围内对系统服务可用,以便以 www-data 运行的守护进程可以使用它,而无需我以 www-data 身份登录来运行它,但要管理它使用我自己的帐户。我们将 sudo 作为实用程序来管理以简单用户身份登录的系统级功能的原因。
    猜你喜欢
    • 2023-04-03
    • 2021-12-02
    • 2022-11-08
    • 1970-01-01
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    • 2015-06-13
    • 2022-10-22
    相关资源
    最近更新 更多