import

Ansible allows unchecked imports of some libraries from specific directories. Importing any other Python library requires handling import errors. This enables support for sanity tests such as validate-modules and provides better error messages to the user.

Handling import errors

In modules

Instead of using 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

Note

The missing_required_lib import above will be used below.

Then in the module code:

module = AnsibleModule(...)

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

In plugins

Instead of using import another_library:

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

Then in the plugin code, for example in __init__ of the plugin:

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

When used as base classes

Important

This solution builds on the previous two examples. Make sure to pick the appropriate one before continuing with this solution.

Sometimes an import is used in a base class, for example:

from another_library import UsefulThing

class CustomThing(UsefulThing):
    pass

One option is make the entire class definition conditional:

if not ANOTHER_LIBRARY_IMPORT_ERROR:
    class CustomThing(UsefulThing):
        pass

Another option is to define a substitute base class by modifying the exception handler:

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

Allowed unchecked imports

Ansible allows the following unchecked imports from these specific directories:

  • ansible-core:

    • For lib/ansible/modules/ and lib/ansible/module_utils/, unchecked imports are only allowed from the Python standard library;

    • For lib/ansible/plugins/, unchecked imports are only allowed from the Python standard library, from public dependencies of ansible-core, and from ansible-core itself;

  • collections:

    • For plugins/modules/ and plugins/module_utils/, unchecked imports are only allowed from the Python standard library;

    • For other directories in plugins/ (see the community collection requirements for a list), unchecked imports are only allowed from the Python standard library, from public dependencies of ansible-core, and from ansible-core itself.

Public dependencies of ansible-core are:

  • Jinja2

  • PyYAML

  • MarkupSafe (as a dependency of Jinja2)