【问题标题】:Virtual environments suddenly broken (No module named 'contextlib')虚拟环境突然损坏(没有名为“contextlib”的模块)
【发布时间】:2021-10-04 00:39:05
【问题描述】:

在 Python 中编程时,我经常使用虚拟环境(使用 venv)。这总是很好,但最近我现有的一些虚拟环境似乎“坏了”。当我尝试激活和使用它们时,我收到以下错误:

Failed to import the site module
Traceback (most recent call last):
  File "c:\temp\virtualenv\lib\site.py", line 703, in <module>
    main()
  File "c:\temp\virtualenv\lib\site.py", line 683, in main
    paths_in_sys = addsitepackages(paths_in_sys)
  File "c:\temp\virtualenv\lib\site.py", line 282, in addsitepackages
    addsitedir(sitedir, known_paths)
  File "c:\temp\virtualenv\lib\site.py", line 204, in addsitedir
    addpackage(sitedir, name, known_paths)
  File "c:\temp\virtualenv\lib\site.py", line 173, in addpackage
    exec(line)
  File "<string>", line 1, in <module>
  File "c:\temp\virtualenv\lib\importlib\util.py", line 13, in <module>
    from contextlib import contextmanager
ModuleNotFoundError: No module named 'contextlib'

这很奇怪,因为contextlib 是标准 Python 库的一部分,我不明白为什么它找不到它。由于这个错误,我什至无法运行 pythonpython --version 或其他不需要加载任何 Python 模块的选项)或 pip(甚至 pip --version 都不起作用)。

之前有人问过并回答过这个问题,比如herehere,但是没有一个答案解释了为什么会发生这个错误,并且都只提供了一种解决方法,即删除并重新创建虚拟环境。这很令人沮丧,因为我并不总是知道我以前安装了哪些软件包,而且我现在不能pip freeze,所以重新创建相同的虚拟环境可能需要很多时间。

我想知道为什么会出现这个错误,以及是否有不强制我重新创建虚拟环境的解决方案。

排除其他一些不相关的问题:

  • 我的操作系统是 Windows 10。
  • 虚拟环境是使用 venv 和 Python 3.x(主要是 3.6 或更高版本)创建的。
  • 我没有移动(重新定位)虚拟环境。
  • 虚拟环境位于本地目录(不是网络驱动器)上。

【问题讨论】:

    标签: python importerror python-venv


    【解决方案1】:

    很难说到底发生了什么事情会破裂。

    如果由于某种原因仅缺少 contextlib,您可以将其从 Python 安装目录复制回 venv 的库目录。这同样适用于其他文件(实际上,您可以使用非virtualenv 解释器使用python -m venv THATDIRECTORY(或python -m virtualenv,如果您使用virtualenv 而不是venv)简单地“重新初始化”同一目录中的venv修复它)。

    然后,pip freeze virtualenv 的内容并正确地重新创建它。

    如果这一切都失败了,您仍然可以查看 venv 库目录中的各种元数据文件,以找出您已安装的软件包版本,这样您就可以让重新创建的 venv 重回正轨。你永远不应该认为 virtualenv 是永恒的。使用例如pip-tools 将您的依赖项锁定到您可以随时重新安装的已知集合。

    【讨论】:

    • 不仅仅是contextlib。如果我复制它,pip 会抱怨缺少runpy。然后pkgutil。然后logging... 不需要复制这些库。在我的其他工作虚拟环境中,这些包都不存在。所以有些东西(或应该)指向正确的位置,但我不知道这是在哪里确定的。
    • 只是运行python -m venv &lt;my_broken_env&gt; 似乎确实可以解决它。我试图弄清楚发生了什么变化,以及是否能找到这种行为的解释。感谢您的建议!
    【解决方案2】:

    在我的案例中,我找到了错误的(可能)原因。 显然,我的一些虚拟环境是用virtualenv 而不是venv 制作的。

    使用virtualenv 创建的虚拟环境的潜在“破坏”是documented

    创建的 python 虚拟环境通常不是独立的。 (...) 这确实意味着如果您升级系统 python,您的虚拟环境可能会中断,所以要小心。

    venv 似乎没有这个问题,或者至少看起来更容易修复它。 venv 生成一个文件venv.cfg,其中包含系统解释器的位置:

    home = C:\Python\3.6-64
    include-system-site-packages = false
    version = 3.6.8
    

    因此,即使您的系统范围的 Python 安装已更改,您也可以轻松更新此文件中的位置。

    注意:似乎可以通过运行以下命令从 virtualenv“更新”到 venv:

    python -m venv &lt;existing_virtual_env_directory&gt;

    我不确定这是否能保证有效。 venv 的文档说明:

    在 3.4 版中更改:在早期版本中,如果目标目录已经存在,则会引发错误,除非提供了 --clear--upgrade 选项。现在,如果指定了现有目录,则删除其内容并处理该目录,就像它是新创建的一样。

    但是,就我而言,没有删除已安装的模块,结果是一个工作的虚拟环境:-)

    【讨论】:

    • 请注意,这是部分答案。我有几个虚拟环境,它们都不包含“contextlib”,其中一些正常工作,有些则没有。我一直无法找出环境之间的区别。我想这与找到系统解释器的方式有关,并且行为在 python 和/或 pip 版本之间发生了变化。如果我有更好的解释,我会更新这个答案。我仍然愿意接受其他答案或 cmets!
    猜你喜欢
    • 1970-01-01
    • 2019-03-03
    • 2021-11-24
    • 2017-09-11
    • 1970-01-01
    • 1970-01-01
    • 2018-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多