导入
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
的出现都必须正确处理在发生它的模块或插件中。