python-动态加载-模块-类-对象

有时希望从配置文件等地获取要被动态加载的 module,但是所读取的配置项通常为字符串类型,无法用 import 加载.

例如:

1
2
3
4
5
>>> import 'os'
File "<stdin>", line 1
import 'os'
^
SyntaxError: invalid syntax

使用内建函数import

1
2
>>> __import__('os')
<module 'os' from '/usr/lib64/python2.7/os.pyc'>

但使用import的时候,如果module字符串有点号(.), 会有问题:

1
2
>> __import__('os')
<module 'os' from '/usr/lib64/python2.7/os.pyc'> #会发现与__import__('os')一样

方法1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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())))
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)
def import_module(import_str):
"""Import a module.
.. versionadded:: 0.3
"""
__import__(import_str)
return sys.modules[import_str]

参考:https://github.com/openstack/oslo.utils/blob/master/oslo_utils/importutils.py

方法2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def import_object(name):
# type: (_BaseString) -> Any
"""Imports an object by name.
import_object('x') is equivalent to 'import x'.
import_object('x.y.z') is equivalent to 'from x.y import z'.
"""
if not isinstance(name, str):
# on python 2 a byte string is required.
name = name.encode('utf-8')
if name.count('.') == 0:
return __import__(name, None, None)
parts = name.split('.')
obj = __import__('.'.join(parts[:-1]), None, None, [parts[-1]], 0)
try:
return getattr(obj, parts[-1])
except AttributeError:
raise ImportError("No module named %s" % parts[-1])