动态导入的模块认为它没有类。

6 浏览
0 Comments

动态导入的模块认为它没有类。

我正在制作一个应用程序,它会在名为“sources”的文件夹中查找.py文件,并在其中查找继承了我定义的名为“SourceBase”的类的类。如果它们继承了SourceBase,我想要创建该类的一个新实例来进行操作。\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的格式帮助,没有找到任何一种以内联方式“突出显示”的方法,即将文本背景设置为灰色。它将有助于突出显示我试图传达的问题的部分。]

0
0 Comments

动态导入模块时,模块不认为自己有类的问题的出现原因是`__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)
    ...

这样,问题就可以得到解决。

0
0 Comments

动态导入模块时,模块没有认为它具有类的原因是因为在导入模块时,返回的通常是顶级包(第一个点之前的部分)而不是名为name的模块。然而,当给出非空的fromlist参数时,返回的是名为name的模块。

解决方法是将module=__import__(searchpath+'.'+modname)替换为module=__import__(searchpath+'.'+modname, None, None, "*")。这与"from sources.source1 import *"相同,告诉__import__获取给定模块中的所有内容。

作者还表示他/她进行了一些调试工作,但是这个解决方案起作用了。他/她花了几个小时来解决这个问题,非常感谢。

0