【问题标题】:Tox and lib and lib64 and site-packagesTox 和 lib 以及 lib64 和站点包
【发布时间】:2017-05-23 22:14:47
【问题描述】:

我正在使用 toxcoverage.py 在我的持续构建服务器中运行我的 Python 项目的测试。我还使用python3.5 setup.py install 安装了来自供应商(PyPI 上不可用)的包pkg_x,它放在/usr/lib/python3.5/site-packages 中。现在我需要将该包提供给测试代码。

我当前的tox.ini 看起来像这样:

[tox]
envlist = py35

[testenv]
deps = nose
       coverage
commands = coverage run -m nose []
sitepackages = True

然后我像这样运行测试:

python3.5 -m tox -- --verbose --with-doctest

这非常失败 - 我的本地 setup.py 中列出的依赖包(例如 more_itertools 之类的公共内容)都找不到,即使它确实创建了像 .tox/py35/lib/python3.5/site-packages/more_itertools 这样似乎包含相关包的目录。如果我启动.tox/py35/bin/python3.5sys.path 看起来像这样:

>>> [re.compile('.*\\.tox').sub('.tox', x) for x in sys.path]
['',
 '.tox/py35/lib64/python35.zip',
 '.tox/py35/lib64/python3.5', 
 '.tox/py35/lib64/python3.5/plat-linux',
 '.tox/py35/lib64/python3.5/lib-dynload',
 '/usr/lib64/python3.5',
 '/usr/lib/python3.5',
 '.tox/py35/lib/python3.5/site-packages']

如果我从我的tox.ini 中删除sitepackages = True 行,那么我会走得更远,在像more_itertools 这样的包中,现在可以找到我的setup.py 依赖项中的其余内容,但是供应商包pkg_x我上面提到的还是找不到。 sys.path 看起来像这样:

>>> [re.compile('.*\\.tox').sub('.tox', x) for x in sys.path]
['',
 '.tox/py35/lib64/python35.zip',
 '.tox/py35/lib64/python3.5', 
 '.tox/py35/lib64/python3.5/plat-linux',
 '.tox/py35/lib64/python3.5/lib-dynload',
 '/usr/lib64/python3.5',
 '/usr/lib/python3.5',
 '.tox/py35/lib/python3.5/site-packages',
 '/usr/lib64/python3.5/site-packages',
 '/usr/lib/python3.5/site-packages']

在这两种情况下,.tox/py35/ 似乎都不会在任何地方包含供应商包pkg_x。尽管在我手动启动 .tox/py35/bin/python3.5 时会列出目录 /usr/lib/python3.5/site-packages,但在运行测试时实际上并没有找到 pkg_x

看起来sitepackages = True 的效果与它记录在案的效果相反 http://tox.readthedocs.io/en/latest/config.html#confval-sitepackages=True|False 对吧?

非常感谢您的建议!

【问题讨论】:

标签: python testing coverage.py tox


【解决方案1】:

Tox 创建一个virtualenv,然后在该环境中运行它的测试。

--sitepackages 参数是一个开关,用于确定 virtualenv 是否可以访问全局安装的包。

运行 tox 的“正常”方式是简单地说tox;通过 pip 或 OS 包安装它应该把它放到你的路径中。即:

$ tox

这和说的一样:

$ tox -c tox.ini

如果你直接调用 tox,python -m tox,它可能会做一些事情,但这对我来说是一个危险信号。这个命令似乎不太可能激活相关的虚拟环境,这可以解释你的包可用性问题。它适合,因为当你省略 sitepackages 时,它实际上添加了全局包,因为它认为它在 virtualenv 中,所以添加了它认为是 local 的站点包,尽管它们实际上是全局的。当你使它成为真的时,相反的情况会发生,因为当它去寻找全局包时它找不到它们。无论如何,因为你没有像预期的那样调用 tox,所以它和我们一样困惑。

所以只需使用提供的tox 命令。

但还有更多:你说你有一个必需的包,但在 pypi 上不可用。那么tox要怎么安装呢? tox 文档提出了几种方法(使用 requirements.txt),但这里最直接的描述是激活 env 并手动安装。

如果您需要进一步调试也很好:进入.tox 目录并手动激活venv。例如:

$ source .tox/testenv/bin/activate

(其中testenv 是您在tox.ini 中括号内使用的名称)。

现在安装包,但是你以前做过的,例如:pip install pkg_x

以这种方式完成后停用 venv:

$ deactivate

现在试试tox

如果我们在正确的轨道上learn more about virtualenv here

【讨论】:

  • 谢谢 - 我相信你是绝对正确的,我的理解需要工作。但是,建议的预安装到虚拟环境中的解决方案将不起作用,因为这是在连续构建服务器中,每次运行都会重建工作环境。每次运行测试时我都必须安装它,并且安装需要人工交互。
  • 我使用python3 -m tox 而不是简单的tox 的原因是我可以控制使用哪个版本的python 来调用Tox,而不是依赖于@987654342 中的shebang 行@ 脚本。我认为这是一个受支持的用例?
  • 对于依赖项,请使用 tox 的 DEPS=。对于版本,这是 tox 的关键销售宣传......它同时测试多个版本的 python。您可以在 tox 中配置每个环境,然后它将在每个环境上构建和测试。 Check the manual ;-)
【解决方案2】:

看来我的问题的解决方案是更改我的tox.ini 中的commands 行:

commands = coverage run -m nose []

到这里:

commands = python -m coverage run -m nose []

效果是python 现在是一个virtualenv-mapped 命令,它加载正确的Python 解释器,加载coverage 模块并运行它。如果没有python -m,它只会在我的PATH 中找到任何coverage 可执行文件并运行它,结果无法预测。 whitelist_externals 可以使用,但只能解决问题。

然后如果我添加sitepackages = True 行,它会成功看到我从供应商安装的pkg_x,并且我的测试成功。

【讨论】:

  • @john-mee 上面的回答向我展示了必要的调查工具 - 即在 .tox 目录中加载 virtualenv 以查看它看到的内容。
  • 另一个变体可能是nosetests --with-coverage ...
猜你喜欢
  • 2014-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-29
  • 1970-01-01
  • 2010-10-29
  • 2017-07-11
相关资源
最近更新 更多