Bundles
A bundle is a Python module installed using the Pelix
Framework
instance or a
BundleContext
object.
Each bundle is associated to an ID, an integer that is unique for a framework instance, and to a symbolic name, i.e. its module name. The framework itself is seen as the bundle which ID is always 0.
Because installing a bundle is in fact importing a module, no code should be written to be executed at module-level (except the definition of constants, the import of dependencies, …). Initialization must be done in the bundle activator (see below).
Life-cycle

Unlike a module, a bundle has a life-cycle and can be in one of the following states:
State |
Description |
---|---|
INSTALLED |
The Python module has been correctly imported, the bundle goes to the RESOLVED state |
RESOLVED |
The bundle has not been started yet or has been stopped |
STARTING |
The |
ACTIVE |
The bundle activator has been called and didn’t raise any error |
STOPPING |
The |
UNINSTALLED |
The bundle has been removed from the framework (only visible by remaining references to the bundle) |
The update process of a bundle is simple:
if it was active, the bundle is stopped: other bundles are notified of this transition, and its services are unregistered
the module is updated, using the importlib.reload() method
if the update fails, the previous version of the module is kept, but the bundle is not restarted.
if the update succeeds and the bundle was active, the bundle its restarted
Bundle Activator
A bundle activator is a class providing the
start()
and
stop()
methods, which are called by the
framework according to the bundle life-cycle.
Warning
The framework is locked during transitions in bundles states, which means
during the calls to start()
and
stop()
.
Therefore, it is highly recommended to return quickly from those methods.
For example, it may be necessary to use threads to complete the initialization
before registering services when the bundle starts.
On the other hand, it is recommended to wait for all resources to be released
before exiting the stop()
, e.g. to
wait for all threads started by the bundle to terminate.
- class pelix.constants.BundleActivator
This decorator must be applied to the class that will be notified of the life-cycle events concerning the bundle. A bundle can only have one activator, which can implement the following methods:
- start(context: BundleContext) None
This method is called when the bundle is in STARTING state. If this method returns without raising an exception, the bundle goes immediately into the ACTIVE state. If an exception is raised, the bundle is stopped.
During the call of this method, the framework is locked. It is therefore necessary that this method returns as soon as possible: all time-consuming tasks should be executed in a new thread or queued.
- stop(context: BundleContext) None
This method is called when the bundle is in STOPPING state. After this method returns or raises an exception, the bundle goes into the RESOLVED state.
All resources consumed by the bundle should be released before this method returns.
Warning
A bundle activator must be instantiable without constructor argument,
i.e. not have arguments other than self
in its __init__
method.
A class is defined as the bundle activator if it is decorated with
@BundleActivator
, as shown in the following snippet.
It is also recommended to let that class inherit from ActivatorProto
to
benefit from its typing.
from pelix.constants import ActivatorProto, BundleActivator
from pelix.framework import BundleContext
@BundleActivator
class Activator(ActivatorProto):
"""
Bundle activator template
"""
def start(self, context):
"""
Bundle is starting
"""
print("Start")
def stop(self, context):
"""
Bundle is stopping
"""
print("Stop")
Note
The previous declaration of the activator, i.e. declaring module member
named activator
, is deprecated and its support will be removed in
version 1.0.
Bundle Context
A context is associated to each bundle, and allows it to interact with the
framework.
It is unique for a bundle and can be used until the latter is removed from
the framework.
It is not recommended to keep references to BundleContext
objects as they
can imply a stall reference to the bundle they describe.
A bundle must use its context to register and to look up services, to request
framework information, etc..
All the available methods are described in the API chapter. Here are the most used ones concerning the handling of bundles:
- class pelix.framework.BundleContext(framework: Framework, bundle: Bundle)
The bundle context is the link between a bundle and the framework. It is unique for a bundle and is created by the framework once the bundle is installed.
- Parameters:
framework – Hosting framework
bundle – The associated bundle
- get_bundle(bundle_id: None | int | Bundle = None) Bundle
Retrieves the
Bundle
object for the bundle matching the given ID (int). If no ID is given (None), the bundle associated to this context is returned.- Parameters:
bundle_id – A bundle ID (optional)
- Returns:
The requested
Bundle
object- Raises:
BundleException – The given ID doesn’t exist or is invalid
- get_bundles() List[Bundle]
Returns the list of all installed bundles
- Returns:
A list of
Bundle
objects
- install_bundle(name: str, path: None | str | Path = None) Bundle
Installs the bundle (module) with the given name.
If a path is given, it is inserted in first place in the Python loading path (
sys.path
). All modules loaded alongside this bundle, i.e. by this bundle or its dependencies, will be looked after in this path in priority.Warning
The behavior of the loading process is subject to changes, as it does not allow to safely run multiple frameworks in the same Python interpreter, as they might share global module values.
- Parameters:
name – The name of the bundle to install
path – Preferred path to load the module (optional)
- Returns:
The
Bundle
object of the installed bundle- Raises:
BundleException – Error importing the module or one of its dependencies
- install_package(path: str | Path, recursive: bool = False) Tuple[Set[Bundle], Set[str]]
Installs all the modules found in the given package (directory). It is a utility method working like
install_visiting()
, with a visitor accepting every module found.- Parameters:
path – Path of the package (folder)
recursive – If True, installs the modules found in sub-directories
- Returns:
A 2-tuple, with the list of installed bundles (
Bundle
) and the list of the names of the modules which import failed.- Raises:
ValueError – The given path is invalid
- install_visiting(path: str | Path, visitor: Callable[[str, bool, str], bool]) Tuple[Set[Bundle], Set[str]]
Looks for modules in the given path and installs those accepted by the given visitor.
- The visitor must be a callable accepting 3 parameters:
fullname – The full name of the module
is_package – If True, the module is a package
module_path – The path to the module file
- Parameters:
path – Root search path (folder)
visitor – The visiting callable
- Returns:
A 2-tuple, with the list of installed bundles (
Bundle
) and the list of the names of the modules which import failed.- Raises:
ValueError – Invalid path or visitor
Listening to bundle events
The bundle context can be used to register to bundle events, using the following methods:
- class pelix.framework.BundleContext(framework: Framework, bundle: Bundle)
The bundle context is the link between a bundle and the framework. It is unique for a bundle and is created by the framework once the bundle is installed.
- Parameters:
framework – Hosting framework
bundle – The associated bundle
- add_bundle_listener(listener: BundleListener) bool
Registers a bundle listener, which will be notified each time a bundle is installed, started, stopped or updated.
- The listener must be a callable accepting a single parameter:
event – The description of the event (a
BundleEvent
object).
- Parameters:
listener – The bundle listener to register
- Returns:
True if the listener has been registered, False if it already was
- remove_bundle_listener(listener: BundleListener) bool
Unregisters the given bundle listener
- Parameters:
listener – The bundle listener to remove
- Returns:
True if the listener has been unregistered, False if it wasn’t registered
A bundle listener must implement the following interface:
- class pelix.internals.registry.BundleListener(*args, **kwargs)
Protocol that must be implemented by a bundle listener
- bundle_changed(event: BundleEvent) None
Notified when a bundle event occurred
- Parameters:
event – Bundle event