在E:\nova\nova\service.py 中通过manager_class = importutils.import_class(self.manager_class_name) 得到一个class,然后就可以调用这个class
例如:
class Service(service.Service):
"""Service object for binaries running on hosts.
A service takes a manager and enables rpc by listening to queues based
on topic. It also periodically runs tasks on the manager and reports
its state to the database services table.
"""
def __init__(self, host, binary, topic, manager, report_interval=None,
periodic_enable=None, periodic_fuzzy_delay=None,
periodic_interval_max=None, *args, **kwargs):
super(Service, self).__init__()
self.host = host
self.binary = binary
self.topic = topic
self.manager_class_name = manager
self.servicegroup_api = servicegroup.API()
manager_class = importutils.import_class(self.manager_class_name)
self.manager = manager_class(host=self.host, *args, **kwargs)
这里的importutils 赋值如下:
from oslo_utils import importutils
原来是在oslo_utils 中实现的。其源码如下:
import sys
import traceback
def import_class(import_str):
"""Returns a class from a string including module and class.
.. versionadded:: 0.3
"""
mod_str, _sep, class_str = import_str.rpartition('.')
__import__(mod_str)
try:
return getattr(sys.modules[mod_str], class_str)
except AttributeError:
raise ImportError('Class %s cannot be found (%s)' %
(class_str,
traceback.format_exception(*sys.exc_info())))
原来是通过sys.modules[mod_str] 得到这个这个模块后,通过getattr 返回这个class.
注意这里的import_str是个字符串,在__init__中赋值如下:self.manager_class_name = manager
以E:\nova\nova\cmd\compute.py 为例可以看到这个字符串为nova-compute
def main():
config.parse_args(sys.argv)
logging.setup(CONF, 'nova')
priv_context.init(root_helper=shlex.split(utils.get_root_helper()))
utils.monkey_patch()
objects.register_all()
gmr_opts.set_defaults(CONF)
# Ensure os-vif objects are registered and plugins loaded
os_vif.initialize()
gmr.TextGuruMeditation.setup_autorun(version, conf=CONF)
cmd_common.block_db_access('nova-compute')
objects_base.NovaObject.indirection_api = conductor_rpcapi.ConductorAPI()
objects.Service.enable_min_version_cache()
server = service.Service.create(binary='nova-compute',
topic=compute_rpcapi.RPC_TOPIC)
service.serve(server)
service.wait()
这样在import_class 中就通过import_str.rpartition('.')将nova-compute变成nova.compute
这样就会去加载nova/compute的__init__.py
CELL_TYPE_TO_CLS_NAME = {'api': 'nova.compute.cells_api.ComputeCellsAPI',
'compute': 'nova.compute.api.API',
None: 'nova.compute.api.API',
}
def _get_compute_api_class_name():
"""Returns the name of compute API class."""
cell_type = nova.cells.opts.get_cell_type()
return CELL_TYPE_TO_CLS_NAME[cell_type]
def API(*args, **kwargs):
class_name = _get_compute_api_class_name()
return importutils.import_object(class_name, *args, **kwargs)
可以看到在__init__.py 中的API 同样通过importutils.import_object 来导入具体的class。
其中import_object的源码如下: 可以看到同样调用import_class,这里的的import_str等于nova.compute.api.API
def import_object(import_str, *args, **kwargs):
"""Import a class and return an instance of it.
.. versionadded:: 0.3
"""
return import_class(import_str)(*args, **kwargs)
importutils.import_class
最新推荐文章于 2024-03-24 19:22:34 发布