Tox and lib and lib64 and site-packages

6
我正在使用toxcoverage.py在我的持续构建服务器上运行Python项目的测试。我还安装了一个来自供应商的pkg_x包(不在PyPI上可用),使用python3.5 setup.py install进行安装,它被放置在/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_itertoolssetup.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
非常感谢您的建议!

我在Tox的一个问题上留下了评论,这个问题看起来像是我所遇到的相同的事情: https://github.com/tox-dev/tox/issues/461#issuecomment-303855697 - Ken Williams
tox 创建自己的虚拟环境。您对虚拟环境熟悉吗?在 .tox 目录中激活虚拟环境并从那里进行调试。 - John Mee
2个回答

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

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

通常情况下运行 tox 的方法是直接输入 tox 命令;通过 pip 或操作系统软件包安装后即可将其添加到路径中。例如:

$ tox

这句话的意思是:

$ tox -c tox.ini

当您直接调用tox时,即python -m tox,它可能会执行某些操作,但这对我来说是一个警示信号。该命令似乎不太可能激活相关的虚拟环境,这可以解释您在软件包可用性方面遇到的问题。原因是当您省略sitepackages时,它实际上添加了全局软件包,因为它认为自己在虚拟环境内,所以添加了它认为是“本地”的sitepackages,尽管它们实际上是全局的。当您将其设置为true时,相反的情况发生,因为当它寻找全局软件包时,它找不到它们。无论如何,由于您没有按预期调用tox,因此它和我们一样困惑。
因此,请使用提供的tox命令。
但等等,还有更多:您说您需要的软件包在pypi上不可用。那么,tox要如何安装它呢?tox文档提供了几种方法(使用requirements.txt文件),但在这里描述最直接的方法是手动激活env并手动安装它。
如果您需要进一步进行调试,则可以进入.tox目录并手动激活venv,例如:
$ source .tox/testenv/bin/activate

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

现在按照以前的方式安装软件包,例如:pip install pkg_x

完成后,请使用以下方式停用虚拟环境:

$ deactivate

现在试试 tox 吗?

如果我们走在正确的路上,在这里了解更多关于 virtualenv 的内容


谢谢 - 我相信你说的没错,我的理解肯定还有待提高。但是,预先安装到虚拟环境的建议解决方案行不通,因为这是一个持续构建服务器,在每次运行时都会重新构建工作环境。我必须在每次运行测试时都进行安装,并且安装需要人工干预。 - Ken Williams
我使用 python3 -m tox 而不是简单的 tox 的原因是我可以控制使用哪个版本的 Python 来调用 Tox,而不是依赖于 tox 脚本中的 shebang 行。我认为这是一个受支持的用例? - Ken Williams
1
对于依赖项,请使用tox的DEPS=。至于版本,这是tox的关键卖点...它可以同时测试多个Python版本。您可以在tox中配置每个环境,然后它将在每个环境上构建和测试。请查看手册;-) - John Mee

2

看起来解决我的问题的方法是修改 tox.ini 中的 commands 行,将其从这个改为:

commands = coverage run -m nose []

转换为:

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

效果是现在python是一个虚拟环境映射命令,它加载正确的Python解释器,加载coverage模块,并运行它。没有python -m,它只会找到我PATH中的任何coverage可执行文件并运行它,结果不可预测。可以使用whitelist_externals,但那只是权宜之计。

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

1
@john-mee的回答向我展示了必要的调查工具 - 即在“.tox”目录中加载virtualenv以查看它所看到的内容。 - Ken Williams
另一种变化可能是 nosetests --with-coverage ... - John Mee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接