【问题标题】:Django test runner fails in virtualenv on UbuntuDjango 测试运行器在 Ubuntu 上的 virtualenv 中失败
【发布时间】:2014-11-04 16:17:31
【问题描述】:

我一直在努力解决安装在 Ubuntu 14.04 上的 Python virtualenv 中的 Django 测试运行程序的问题。相同的软件在 MacOS 上运行良好,我认为在早期版本的 Ubuntu 上运行良好。

失败信息是:

ImportError: '<test>' module incorrectly imported from '<base-env>/local/lib/python2.7/site-packages/<package-dir>'. Expected '<base-env>/lib/python2.7/site-packages/<package-dir>'. Is this module globally installed?

错误的完整堆栈跟踪是:

  Traceback (most recent call last):
    File "/home/annalist/anenv/bin/django-admin", line 11, in <module>
      sys.exit(execute_from_command_line())
    File "/home/annalist/anenv/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
      utility.execute()
    File "/home/annalist/anenv/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 377, in execute
      self.fetch_command(subcommand).run_from_argv(self.argv)
    File "/home/annalist/anenv/local/lib/python2.7/site-packages/django/core/management/commands/test.py", line 50, in run_from_argv
      super(Command, self).run_from_argv(argv)
    File "/home/annalist/anenv/local/lib/python2.7/site-packages/django/core/management/base.py", line 288, in run_from_argv
      self.execute(*args, **options.__dict__)
    File "/home/annalist/anenv/local/lib/python2.7/site-packages/django/core/management/commands/test.py", line 71, in execute
      super(Command, self).execute(*args, **options)
    File "/home/annalist/anenv/local/lib/python2.7/site-packages/django/core/management/base.py", line 338, in execute
      output = self.handle(*args, **options)
    File "/home/annalist/anenv/local/lib/python2.7/site-packages/django/core/management/commands/test.py", line 88, in handle
      failures = test_runner.run_tests(test_labels)
    File "/home/annalist/anenv/local/lib/python2.7/site-packages/django/test/runner.py", line 147, in run_tests
      suite = self.build_suite(test_labels, extra_tests)
    File "/home/annalist/anenv/local/lib/python2.7/site-packages/django/test/runner.py", line 96, in build_suite
      tests = self.test_loader.discover(start_dir=label, **kwargs)
    File "/usr/lib/python2.7/unittest/loader.py", line 206, in discover
      tests = list(self._find_tests(start_dir, pattern))
    File "/usr/lib/python2.7/unittest/loader.py", line 287, in _find_tests
      for test in self._find_tests(full_path, pattern):
    File "/usr/lib/python2.7/unittest/loader.py", line 287, in _find_tests
      for test in self._find_tests(full_path, pattern):
    File "/usr/lib/python2.7/unittest/loader.py", line 267, in _find_tests
      raise ImportError(msg % (mod_name, module_dir, expected_dir))
  ImportError: 'test_entity' module incorrectly imported from '/home/annalist/anenv/local/lib/python2.7/site-packages/annalist_root/annalist/tests'. Expected '/home/annalist/anenv/lib/python2.7/site-packages/annalist_root/annalist/tests'. Is this module globally installed?

测试用例在开发环境中运行良好,从源代码分发包安装到 MACOS 开发主机上的新 virtualenv 环境时也运行良好。但是,当我将相同的包安装到 Ubuntu 14.04 主机上的新 virtualenv 中时,测试运行程序会失败并显示上述消息。

问题出现在我创建的一个管理实用程序中,它调用了django-admin 的一些函数(以及其他一些东西)。

Web 搜索显示有关 virtualenv 和 posix 兼容性的错误报告,最近 (2013/14) 在 Ubuntu 发行版中通过在虚拟环境中创建 local 目录来解决这些问题,该目录又包含指向目录的符号链接,这些目录也是可从顶级虚拟环境目录访问。错误消息中显示的路径对应于这些别名目录路径。

(我将此作为问题发布,以便我可以发布我的调查结果和答案,希望它对其他人有用。因此,我不想详细描述我的具体情况软件设置。)

【问题讨论】:

    标签: python django ubuntu virtualenv python-unittest


    【解决方案1】:

    我遇到了完全相同的问题,但不知道发生了什么。最后这是一件愚蠢的事情:

    我有一个类似的布局:

    my_app/
        __init__.py
        tests.py
        tests/
            __init__.py
           test_foo.py
    

    问题是由“tests.py”模块和“tests”包在同一个文件夹中产生的。

    只需删除“tests.py”文件就解决了我的问题。

    希望对你有帮助。

    【讨论】:

    • 很好...让我头疼:)
    • 哦,伙计,我大约需要 5 分钟才能进入愤怒的开发者模式。这么小的东西,谢谢!把我从漫长而暴躁的一天中拯救出来!
    【解决方案2】:

    简答

    我的代码中的修复是使用os.path.realpath 获取已安装包路径的规范化版本,并在调用django-admin 实用程序的命令行上传递此值。就我而言,它看起来像这样:

    approot = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
    

    和:

    with ChangeCurrentDir(approot):
        subprocess_command = (
            "django-admin test --pythonpath=%s --settings=%s --top-level-directory=%s"%
                (approot, settings_module_name, approot)
            )
        status = subprocess.call(subprocess_command.split())
    

    (其中ChangeCurrentDir 是一个上下文处理程序,它使用指定的当前工作目录运行包含的代码)。

    更多详情

    一些进一步的实验表明,我可以通过在 Python 和/或 Django 库代码中将 os.path.abspath 战略性地替换为 os.path.realpath 来“解决”该问题。

    我发现的核心问题在:

    /usr/lib/python2.7/unittest/loader.py
    

    具体来说:

    File "/usr/lib/python2.7/unittest/loader.py", line 267, in _find_tests
        raise ImportError(msg % (mod_name, module_dir, expected_dir))
    ImportError: 'test_entity' module incorrectly imported from ...
    

    loader.py导致此问题的代码是:

            if realpath.lower() != fullpath_noext.lower():
                module_dir = os.path.dirname(realpath)
                mod_name = os.path.splitext(os.path.basename(full_path))[0]
                expected_dir = os.path.dirname(full_path)
                msg = ("%r module incorrectly imported from %r. Expected %r. "
                       "Is this module globally installed?")
                raise ImportError(msg % (mod_name, module_dir, expected_dir))
    

    如果我用这个替换 if 语句:

            if os.path.realpath(realpath).lower() != fullpath_noext.lower():
    

    然后一切都很开心。这证实这是一个符号链接别名问题,因为os.path.realpath() 将任何符号链接解析到底层路径。但这不是可安装软件包的解决方案,因为它涉及修改底层 Python 安装。因此,在探究了根本问题之后,我需要一些更容易攻击的东西。

    下一个调用端口是安装在虚拟环境中的 Django 测试运行程序库。

    <base-env>/local/lib/python2.7/site-packages/django/test/runner.py
    

    特别关注堆栈跟踪的这一部分:

      File "/home/annalist/anenv/local/lib/python2.7/site-packages/django/test/runner.py", line 96, in build_suite
        tests = self.test_loader.discover(start_dir=label, **kwargs)
    

    挖掘这段代码,我发现问题与label 参数有关,该参数默认为'.'(即当前目录)。这里没有明显的简单修复,但它表明问题可能与运行django-admin 时使用的当前目录和/或路径有关。这导致了上述解决方案(这可能有点矫枉过正 - 我不确定是否需要 --pythonpath= 选项,但它对我有用)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-18
      • 2014-02-09
      相关资源
      最近更新 更多