2.6 KiB
title |
---|
Importing code with asyncio |
Determining when it is safe to import code when using asyncio can be tricky because two constraints need to be considered:
- Importing code can do blocking I/O to load the files from the disk
- Importing code in cpython is not thread-safe
Top-level imports
Suppose your imports happen at the top-level (nearly all code at indentation level 0). Home Assistant will import your code before the event loop starts or import it in the import executor when your integration is loaded. In this case, you likely do not need to consider whether your imports are safe.
Imports outside of top-level
If your imports are not happening at top-level, you must carefully consider each import, as the import machinery has to read the module from disk which does blocking I/O. If possible, it's usually best to change to a top-level import, as it avoids much complexity and the risk of mistakes. Importing modules is both CPU-intensive and involves blocking I/O, so it is crucial to ensure these operations are executed in the executor.
If you can be sure that the modules have already been imported, using a bare import
statement is safe since Python will not load the modules again.
If the module will only ever be imported in a single place, the standard executor calls can be used:
- For imports inside of Home Assistant
hass.async_add_executor_job(_function_that_does_late_import)
- For imports outside of Home Assistant:
loop.run_in_executor(None, _function_that_does_late_import)
If the same module may be imported concurrently in different parts of the application, use the thread-safehomeassistant.helpers.importlib.import_module
helper.
If its possible the module may be imported from multiple different paths, use async_import_module
:
Example:
from homeassistant.helpers.importlib import async_import_module
platform = await async_import_module(hass, f"homeassistant.components.homeassistant.triggers.{platform_name}")
Determining if a module is already loaded
If you are unsure if a module is already loaded, you can check if the module is already in sys.modules
. You should know that the module will appear in sys.modules
as soon as it begins loading, and cpython imports are not thread-safe. For this reason, it's important to consider race conditions when code may be imported from multiple paths.