Python 2.7 ImportMismatchError 在 basedir 重命名后由过时的 pycache 引起

标签 python caching python-import pytest importerror

我试图了解这里发生了什么,以便防止类似情况再次发生。

我有一份运行 python 程序的 Jenkins 工作(实际上是 pytest )。它在 virtualenv 中使用 Python 2.7.6。在某些时候,Jenkins 作业被重命名,这会导致 Jenkins 重命名作业工作区存储的目录。通常这不会导致问题,如果出现问题,“删除工作区”往往会解决问题。但由于特定原因,此操作并未完成,工作区仍保持原样。

重命名后,python 程序将拒绝运行,并发出 ImportMismatchError对于特定的 python 模块( conftest.py )。使用 pdb 进行一些调试后我发现 python 模块( conftest.cpython-27-PYTEST.pyc )的缓存版本是从名为 __pycache__ 的目录中加载的。 ,并且该缓存版本包含现在无效的绝对路径。这会导致 ImportMismatch 错误,因为缓存版本的绝对路径与模块源的绝对路径不匹配,但它仍然被视为缓存命中!

我知道这个 pycache 机制取代了“旁边”.pyc python2的缓存机制 - 但是有一些我不明白我的情况的事情:

  1. 为什么 __pycache__鉴于 Jenkins 使用的是 Python 2.7.6,并且这似乎是从 3.2 开始支持的,是否存在? Python2有什么办法可以创建这个目录吗?我注意到它支持创建和读取缓存,这让我感到惊讶 - 这是向后移植到 2.7.6 的吗?
  2. 为什么这个机制在确定缓存版本是否过时时不考虑模块的完整路径?在本例中,python 模块的文件名没有更改,但 basedir(路径)发生了更改。然而,这并没有使缓存失效,因此导致了 ImportMismatch 错误。难道不应该将完整路径用作缓存键的一部分而不仅仅是文件名吗?与旧.pyc除了机制之外,重命名 basedir 并不重要,因为 .py 的相对位置和文件名和.pyc文件保持不变。

我的情况的修复很简单 - 我只是删除了 __pycache__目录。然而我花了两个小时才达到这一点,主要是因为我以前没有处理过这个缓存机制,所以我想了解更多关于这一点。

编辑:这是我看到的完整错误消息 - 没有提及 __pycache__不幸的是,这里有目录或删除它们的说明:

+ pytest -s -v
Traceback (most recent call last):
  File "/srv2/jenkins/shiningpanda/jobs/bcd7891c/virtualenvs/d41d8cd9/local/lib/python2.7/site-packages/_pytest/config.py", line 362, in _importconftest
    mod = conftestpath.pyimport()
  File "/srv2/jenkins/shiningpanda/jobs/bcd7891c/virtualenvs/d41d8cd9/local/lib/python2.7/site-packages/py/_path/local.py", line 680, in pyimport
    raise self.ImportMismatchError(modname, modfile, self)
ImportMismatchError: ('tests.conftest', '/srv2/jenkins/jobs/CI_Job/workspace/tests/conftest.py', local('/srv2/jenkins/jobs/CI_Job_Renamed/workspace/tests/conftest.py'))
ERROR: could not load /srv2/jenkins/jobs/CI_Job_Renamed/workspace/tests/conftest.py

最佳答案

它的存在是因为 pytest 将其重写的字节码缓存在那里(它需要重写它以通过简单的 assert 提供详细的断言)。

至于只有基名才是关键,我猜原因可能与 test modules need unique basenames 的原因相同。 :

Note that using this scheme your test files must have unique names, because pytest will import them as top-level modules since there are no packages to derive a full package name from. In other words, the test files in the example above will be imported as test_app and test_view top-level modules by adding tests/ to sys.path.

至于这是您问题的解决方案 - 错误消息没有告诉您删除 __pycache__目录?绝对应该有。

关于Python 2.7 ImportMismatchError 在 basedir 重命名后由过时的 pycache 引起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43219263/

相关文章:

python - 如何有效地翻转多维 numpy 数组?

python - python的tfidf算法

java - 刷新 XPage 中的配置文件文档

python - Python 中的集成

android - android (kivy) 上的 Python - 某些操作的速度瓶颈?

asp.net - 我可以在模拟器之外使用 Azure 内存缓存(主要用于开发目的)吗?

caching - 面试分配-设计像S3这样的系统

python import 会导致代码膨胀。我这里想错了吗?

python - Python 3 中的导入后 Hook

python - 包模块应该如何相互导入?