我有一个问题需要实例化一个类,但我不确定最佳方法是什么。
想象一下以下代码:
# loadstuff.py
class LoadSomething:
def load(self, filename):
compiled = compile(open(filename).read(), filename, 'exec')
# The part I am stuck on
# How do I get the class name, and how do I instantiate it?
# This is assuming the file name is the same as the class name, only starting with capital letter, and minus file extension
module = compiled. # instantiate class 'Printstuff'
return module
loader = LoadSomething()
module = loader.load("printstuff.py")
module.printSomething() # Should print "Something!"
# printstuff.py
class Printstuff:
def printSomething(self):
print("Something!")
我认为代码(以及问题)主要是为自己说话,如何使用compile(..)
返回并实例化一个新类,以便我可以调用它的方法?
答案 0 :(得分:1)
无需手动编译。使用importlib.import_module()
动态导入模块。
然后,您可以将inspect.getmembers()
与inspect.isclass()
predicate一起使用来查找所有类,包括可能与模块名称匹配的任何类:
import importlib
import inspect
class LoadSomething:
def load(self, modulename):
module = importlib.import_module(modulename)
modname = modulename.rpartition('.')[-1] # support packages too
for clsname, cls in inspect.getmembers(module, inspect.isclass):
if clsname == modname.title():
return cls()
这将返回第一个类的实例,该实例与模块具有相同的名称,已标记。
答案 1 :(得分:0)
基本问题是代码对象(您使用compile()
生成的东西)可以包含任何 Python代码 - 例如它可以定义多个类。因此,您必须指定您正在加载的文件应该如何指示要使用的类。
例如,一个选项是要求它定义一个具有众所周知名称的类。例如:
codeobj = compile(open(filename).read(), filename, 'exec')
globs = {}
locs = {}
exec(codeobj, globs, locs)
cls = globs['Foobar']
obj = cls()
您可以使用execfile()
代替compile()
和exec()
来简化此操作:
globals = {}
locals = {}
execfile(filename, globs, locs)
cls = globs['Foobar']
obj = cls()
很容易想出更复杂的方案。
FWIW,这样做而不是使用imp
,importlib
或__import__
的原因是基于导入的选项使用模块系统。如果这是用于加载插件,您可能不希望这样,所以execfile()
等更合适。