【问题标题】:poetry dependencies not available when running script with tox使用 tox 运行脚本时诗歌依赖项不可用
【发布时间】:2023-04-06 09:28:01
【问题描述】:

我有一个使用诗歌和毒物的 python 项目。它有源代码、测试和脚本(juptext 笔记本)。我无法在脚本中导入开发依赖项,但我可以在测试中导入。

当我遇到这个问题时,我创建了以下最小示例。起初,它不起作用,然后我摆弄它,现在它起作用了。所以我剥离了有实际问题的项目,所以除了项目名称、位置、虚拟环境和 .git 目录之外,它无法区分,但这仍然不起作用。

更新删除所有构建工件和最小示例的 virtualenv 使其再次停止工作

UPDATEscripts: poetry install 行添加到 tox 命令修复最小示例

源代码、测试和脚本如下布局

foo
  +--foo
  |  +--__init__.py
  |
  +--tests
  |  +--__init__.py
  |  +--test_foo.py
  |
  +--scripts
  |  +--foo_script.py
  |
  +--pyproject.toml
  +--tox.ini

文件要么是空的,要么如下:

foo_script.py

import requests

test_foo.py

import requests
import pytest

def test():
    assert True

pyproject.toml

[tool.poetry]
name = "foo"
version = "0.1.0"
description = ""
authors = ["foo maker"]

[tool.poetry.dependencies]
python = "^3.7"
requests = "*"

[tool.poetry.dev-dependencies]
pytest = "^4.6"

[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"

tox.ini

[tox]
envlist = test, scripts
isolated_build = true
skipsdist = true

[testenv]
basepython = python3.7
whitelist_externals =
    pytest
    bash
commands =
    test: pytest
    scripts: bash -c 'python3 scripts/*.py'

当我运行 tox 时,我得到了

test run-test-pre: PYTHONHASHSEED='4126239415'
test run-test: commands[0] | pytest
============================= test session starts ==============================
platform linux -- Python 3.6.9, pytest-5.2.1, py-1.8.0, pluggy-0.13.0
cachedir: .tox/test/.pytest_cache
rootdir: /home/#######/foo
collected 1 item                                                               

tests/test_foo.py .                                                      [100%]

============================== 1 passed in 0.09s ===============================
scripts run-test-pre: PYTHONHASHSEED='4126239415'
scripts run-test: commands[0] | bash -c 'python3 scripts/*.py'
Traceback (most recent call last):
  File "scripts/foo_script.py", line 1, in <module>
    import requests
ModuleNotFoundError: No module named 'requests'
ERROR: InvocationError for command /bin/bash -c 'python3 scripts/*.py' (exited with code 1)
___________________________________ summary ____________________________________
  test: commands succeeded
ERROR:   scripts: commands failed

【问题讨论】:

  • 您是否在全球范围内安装了pytest?名为testtox testenv 应该调用命令pytest,但据我所知,它没有在任何地方声明为依赖项。所以这个 testenv 应该会失败。
  • @sinoroc 显然是这样。没有意识到这一点
  • 据我所知,tox 无法识别 poetrydev-dependencies(我是不知道为什么诗歌在这里发明了自己的东西)。您可能想要遵循的更常见的模式是使用 test extra 来确保将 pytest 等测试依赖项安装在_tox 环境,就像在这个答案中解释的那样:stackoverflow.com/a/59522588/11138259

标签: python tox python-poetry


【解决方案1】:

我相信类似以下的方法应该有效:

pyproject.toml

[tool.poetry]
name = "foo"
version = "0.1.0"
description = ""
authors = ["foo maker"]

[tool.poetry.dependencies]
python = "^3.7"
requests = "*"
#
pytest = { version = "^4.6", optional = true }

[tool.poetry.extras]
test = ["pytest"]

# [tool.poetry.dev-dependencies]
# use 'test' extra instead

[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"

tox.ini

[tox]
envlist = test, scripts
isolated_build = true

[testenv]
basepython = python3.7
whitelist_externals =
    pytest
    bash
extras =
    test
commands =
    test: pytest
    scripts: bash -c 'for f in scripts/*.py; do python "$f"; done'

【讨论】:

    【解决方案2】:

    假设您已经安装了诗歌,并且 tox 和 pytest 是 pyproject.yml 中的依赖项(注意 poetry run,请参阅 https://python-poetry.org/docs/cli/#run):

    [tox]
    envlist = py37
    isolated_build = True
    skipsdist = True
    
    [testenv]
    whitelist_externals = poetry
    commands=
        poetry run pytest
    

    您可以选择在运行测试时通过将最后一位更改为来进行安装(但是您需要在诗歌之外安装 tox,这可能会导致您出现问题)

    commands=
        poetry install
        poetry run pytest
    

    还取决于您的根文件夹和测试所在的位置,您可以通过添加配置 tox 更改目录的路径

    changedir = tests
    

    在这种情况下,如果您在目录 foo 中执行 tox,则整个文件将如下所示:

    [tox]
    envlist = py37
    isolated_build = True
    skipsdist = True
    
    [testenv]
    whitelist_externals = poetry
    commands=
        poetry run pytest
    changedir = tests
    

    【讨论】:

    • @JoelB 我投了反对票。尽管我理解你的两个建议中的想法(我知道它也在诗歌常见问题解答中),但我相信这种做法(在命令中调用诗歌)有点适得其反,或者至少违背 tox 的哲学。此discussion 中的更多详细信息。一个明显的例子是,针对不同版本的依赖项测试项目将变得不可能(或至少非常困难),例如question
    • 很公平,感谢您的解释,我明白其中的道理。
    【解决方案3】:

    首先我需要使用poetry install 安装依赖项。然后将poetry run 附加到命令的开头以启用依赖项。同样运行这样的python脚本只会运行第一个,将其他的名称作为参数传递给第一个程序。而是使用for f in scripts/*.py; do python "$f"; done(参见here

    大家一起

    poetry install
    poetry run bash -c 'for f in scripts/*.py; do python "$f"; done'
    

    【讨论】:

    • 它不是从 tox 虚拟环境中创建一个 poetry 虚拟环境吗?
    • @sinoroc 我不知道,但这是诗歌文档建议的python-poetry.org/docs/faq/#is-tox-supported
    • 我知道,我也在文档中看到了这一点。整件事对我来说没有任何意义。 tox 已经负责将项目及其依赖项安装到虚拟环境中。所以此时没有必要让 poetry 参与进来,除了构建 sdist,这正是 isolated_build = true 所做的,这要归功于 PEP517 和 PEP518。跨度>
    • @sinoroc 我明白你的意思,虽然我个人认为应该由诗歌负责依赖而不是 tox,因为我不会在所有情况下都使用 tox,但我会使用诗歌
    • 是的。取决于你想用 tox 做什么。我不完全确定您的用例是否需要 tox 。通常 tox 用于针对多个 Python 版本进行测试。并且还针对依赖项的多个版本,这就是 poetry 肯定会阻碍 tox 的地方,例如参见 this questionthis issue。在这些情况下,poetry 会重新安装项目和依赖项,从而取消之前由 tox 完成的工作。
    猜你喜欢
    • 2022-12-17
    • 2021-10-17
    • 2023-04-06
    • 1970-01-01
    • 2023-02-07
    • 1970-01-01
    • 2022-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多