导入

Ansible 允许对某些目录中的某些库进行未经检查的导入。导入任何其他 Python 库都需要处理导入错误。这使得支持诸如validate-modules之类的健全性测试成为可能,并为用户提供了更好的错误消息。

重要

请参阅常见问题,了解有关解决此测试报告的错误的常见问题的答案。

处理导入错误

Ansible 在许多主机上执行,并且可以同时使用多个 Python 解释器,这些解释器甚至可能具有不同的版本。为了确保用户获得可操作且易于理解的错误,我们尝试确保模块/插件中任何非核心导入都受到保护,以避免出现回溯,大多数用户无法理解,更不用说用来解决问题了。

Ansible 执行此操作的另一个原因是导入代码以进行检查。这允许 Ansible 基于代码轻松地进行测试、记录、配置等,而无需在任何地方安装所有必需项,尤其是在这并非执行代码的上下文时。

以下代码显示了如何避免导入错误,然后使用提供的missing_required_lib来确保用户知道缺少哪个库、在哪个主机上缺少以及需要它的特定解释器。

在模块中

不要使用import another_library

import traceback

from ansible.module_utils.basic import missing_required_lib

try:
    import another_library
except ImportError:
    HAS_ANOTHER_LIBRARY = False
    ANOTHER_LIBRARY_IMPORT_ERROR = traceback.format_exc()
else:
    HAS_ANOTHER_LIBRARY = True
    ANOTHER_LIBRARY_IMPORT_ERROR = None

注意

上面的missing_required_lib导入将在下面使用。

然后在模块代码中,通常在main方法内

module = AnsibleModule(...)

if not HAS_ANOTHER_LIBRARY:
    module.fail_json(
        msg=missing_required_lib('another_library'),
        exception=ANOTHER_LIBRARY_IMPORT_ERROR)

在插件中

不要使用import another_library

try:
    import another_library
except ImportError as imp_exc:
    ANOTHER_LIBRARY_IMPORT_ERROR = imp_exc
else:
    ANOTHER_LIBRARY_IMPORT_ERROR = None

然后在插件代码中,例如在插件的run方法中(某些插件没有run方法,需要在__init__方法中使用)

if ANOTHER_LIBRARY_IMPORT_ERROR:
    raise AnsibleError('another_library must be installed to use this plugin') from ANOTHER_LIBRARY_IMPORT_ERROR

用作基类时

重要

此解决方案基于前两个示例。请务必在继续此解决方案之前选择合适的方案。

有时在基类中使用导入,例如

from another_library import UsefulThing

class CustomThing(UsefulThing):
    pass

一种选择是使整个类定义成为条件性的

if not ANOTHER_LIBRARY_IMPORT_ERROR:
    class CustomThing(UsefulThing):
        pass

另一种选择是通过修改异常处理程序来定义替代基类

try:
    from another_library import UsefulThing
except ImportError:
    class UsefulThing:
        pass
    ...

允许的未经检查的导入

Ansible 允许从这些特定目录进行以下未经检查的导入

  • ansible-core

    • 对于lib/ansible/modules/lib/ansible/module_utils/,仅允许从 Python 标准库进行未经检查的导入;

    • 对于lib/ansible/plugins/,仅允许从 Python 标准库、ansible-core 的公共依赖项以及 ansible-core 本身进行未经检查的导入;

  • 集合

    • 对于plugins/modules/plugins/module_utils/,仅允许从 Python 标准库进行未经检查的导入;

    • 对于plugins/中的其他目录(有关列表,请参阅社区集合要求),仅允许从 Python 标准库、ansible-core 的公共依赖项以及 ansible-core 本身进行未经检查的导入。

ansible-core 的公共依赖项是

  • Jinja2

  • PyYAML

  • MarkupSafe(作为 Jinja2 的依赖项)

常见问题 (FAQ)

为什么我的模块或插件有效时会收到一个ImportError

import健全性测试与其他测试非常不同。根据设计,它只能看到 Python 标准库中的模块。这意味着您的模块或插件可以在您的剧本、集成测试和单元测试中工作,而不会失败import健全性测试。

所有ImportError的出现都必须正确处理在发生它的模块或插件中。

为什么测试没有使用我指定的 Python 解释器?

健全性测试将使用您指定的 Python 解释器。但是,它将使用该 Python 解释器创建它自己的虚拟环境。

所有ImportError的出现都必须正确处理在发生它的模块或插件中。

如何使用自定义虚拟环境?

这是不可能的,因为这样做会违背测试的目的。

所有ImportError的出现都必须正确处理在发生它的模块或插件中。

如何指定在哪里查找我的导入?

这是不可能的,因为这样做会违背测试的目的。

所有ImportError的出现都必须正确处理在发生它的模块或插件中。

如何指定要使用的哪个 requirements 文件?

这是不可能的,因为这样做会违背测试的目的。

所有ImportError的出现都必须正确处理在发生它的模块或插件中。

如何在不更改代码的情况下修复ImportError

无法修复插件或模块中的ImportError,而不对其进行更改。

所有ImportError的出现都必须正确处理在发生它的模块或插件中。