如何在Python中将完全限定类名映射到其类对象?
你可以这样获取一个Python对象的完整类名(可以参考这个问题):
>>> import Queue
>>> q = Queue.PriorityQueue()
>>> def fullname(o):
return o.__module__ + "." + o.__class__.__name__
...
>>> fullname(q)
'Queue.PriorityQueue'
>>>
那么,反过来怎么做呢?也就是说,如何将一个完整的类名,比如'Queue.PriorityQueue'
,映射到它对应的类对象(Queue.PriorityQueue
)呢?
3 个回答
0
在Python中,标识符其实不是用来这样使用的,不过通过sys.modules
和__import__
,你可以实现你想要的功能。
import sys
def get_by_qualified_name(name):
parts = name.split(".")
module_name = parts[0]
attribute_names = parts[1:]
if module_name not in sys.modules:
__import__(module_name)
result = sys.modules[module_name]
for attribute_name in attribute_names:
result = getattr(result, attribute_name)
return result
示例用法
my_queue = get_by_qualified_name("Queue.Queue")()
my_queue.put("Hello World")
print my_queue.get() # prints "Hello World"
如果模块在一个包里,而这个包没有把它作为__ALL__
的一部分导入,那么这个方法会失败。虽然可以解决这个问题,但需要更复杂的使用__import__
。
1
适用于 Python 2.6/2.7
import sys
def hasModule(moduleName):
return moduleName in sys.modules
def getModule(moduleName):
if hasModule(moduleName):
return sys.modules[moduleName]
def loadModule(moduleName):
if not hasModule(moduleName):
return __import__(moduleName)
return getModule(moduleName)
def createInstance(fqcn, *args):
paths = fqcn.split('.')
moduleName = '.'.join(paths[:-1])
className = paths[-1]
module = loadModule(moduleName)
if module is not None:
return getattr(module, className)(*args)
pq = "Queue.PriorityQueue"
pqObj = createInstance(pq)
pqObj.put(1)
print pqObj.get() #1
11
在Python 2.7中,你可以使用importlib:
from importlib import import_module
name = 'xml.etree.ElementTree.ElementTree'
parts = name.rsplit('.', 1)
ElementTree = getattr(import_module(parts[0]), parts[1])
tree = ElementTree()
在旧版本中,你可以使用__import__
这个函数。默认情况下,它会返回一个包的顶层导入(比如说xml
)。不过,如果你给它传一个非空的fromlist
,它就会返回你指定的模块:
name = 'xml.etree.ElementTree.ElementTree'
parts = name.rsplit('.', 1)
ElementTree = getattr(__import__(parts[0], fromlist=['']), parts[1])
tree = ElementTree()