动态导入的模块认为它没有类。
动态导入的模块认为它没有类。
我正在制作一个应用程序,它会在名为“sources”的文件夹中查找.py文件,并在其中查找继承了我定义的名为“SourceBase”的类的类。如果它们继承了SourceBase,我想要创建该类的一个新实例来进行操作。\n我已经通过以下帖子进行了一些研究,我大部分都理解了:\n
- \n
- 动态导入模块,然后实例化具有特定基类的对象
- 如何动态加载Python类
- 动态加载Python模块
\n
\n
\n
\n我的文件夹设置如下,我认为这是相关的:\n
EPDownloader [package] \ epdownloader.py [main] SourceBase.py [包含SourceBase类] imageutils.py [这个类将查找和动态加载sources包中的类] sources [package] \ source1.py [有一个扩展SourceBase的类] source2.py ...其他插件在这里...
\n我的问题是,我正在使用以下代码(来自我上面列出的其他堆栈溢出问题),它正在搜索我的模块中的类,但它找不到我的类。它只是跳过它们。我不知道错在哪里。这是我的执行搜索的代码(它基于我发布的第一个链接):\n
def getSources(self): pluginbase=SourceBase.SourceBase searchpath='sources' #We want to iterate over all modules in the sources/ directory, allowing the user to make their own. for root, dirs, files in os.walk('./'+searchpath): print('files: ',files) candidates = [fname for fname in files if fname.endswith('.py') and not fname.startswith('__')] classList=[] if candidates: for c in candidates: modname = os.path.splitext(c)[0] print('importing: ',modname) module=__import__(searchpath+'.'+modname) #<-- You can get the module this way print('Parsing module '+modname) for cls in dir(module): #<-- Loop over all objects in the module's namespace print('Inspecting item from module: '+str(cls)) cls=getattr(module,cls) #this seems to still be a module when it hits source1 print('Get attribute: '+str(cls)) if (inspect.isclass(cls)): # Make sure it is a class print('...is a class') if inspect.getmodule(cls)==module: # Make sure it was defined in module, not just imported print('...is in a module') if issubclass(cls,pluginbase): # Make sure it is a subclass of base print('...subclasses '+pluginbase.__name__) classList.append(cls) print(classList)
\n这是它给我提供的相关输出(我裁剪了很多其他代码输出的内容):\n
Inspecting item from module: source1 Get attribute:[] <---表示它未能找到源类
\n我很确定我的子类化是有效的,这是类的一部分摘录:\n
from EPDownloader import SourceBase class source1(SourceBase.SourceBase): def __init__(self): pass
\n我被这个问题困扰了。我已经花了几个小时在上面,不知道该怎么办。我有一种感觉,这是一个简单的修复,我没有看到。有人可以帮我找到这个错误吗?\n[注意:我查看了StackOverflow的格式帮助,没有找到任何一种以内联方式“突出显示”的方法,即将文本背景设置为灰色。它将有助于突出显示我试图传达的问题的部分。]
动态导入模块时,模块不认为自己有类的问题的出现原因是`__import__`方法错误地导入了整个包,而不是单个模块。为了解决这个问题,可以在导入模块前先将搜索路径添加到`sys.path`中,然后使用`__import__`方法导入单个模块。下面是修复代码的示例:
for c in candidates: modname = os.path.splitext(c)[0] print('importing: ',modname) # 新代码 sys.path.insert(0, searchpath) module=__import__(modname) # <-- 这样可以正确地获取模块 # 结束新代码 print('Parsing module '+modname) ...
这样,问题就可以得到解决。
动态导入模块时,模块没有认为它具有类的原因是因为在导入模块时,返回的通常是顶级包(第一个点之前的部分)而不是名为name的模块。然而,当给出非空的fromlist参数时,返回的是名为name的模块。
解决方法是将module=__import__(searchpath+'.'+modname)
替换为module=__import__(searchpath+'.'+modname, None, None, "*")
。这与"from sources.source1 import *"相同,告诉__import__获取给定模块中的所有内容。
作者还表示他/她进行了一些调试工作,但是这个解决方案起作用了。他/她花了几个小时来解决这个问题,非常感谢。