【问题标题】:Dynamically imported module doesn't think it has class动态导入的模块认为它没有类
【发布时间】:2014-01-12 21:26:34
【问题描述】:

设置:Python 3.3

我正在制作一个应用程序,该应用程序在名为“sources”的文件夹中查找 .py 文件,并在其中查找扩展了我定义的名为“SourceBase”的类的类。如果他们扩展 SourceBase,我想创建一个新的类实例来处理。

我通过以下帖子进行了相当多的研究,我大部分都了解:

我的文件夹设置是这样的,我认为这是相关的:

EPDownloader [package]
\
 epdownloader.py [main]
 SourceBase.py [contains SourceBase class]
 imageutils.py [this class will find and dynamically load the classes in the sources package]
 sources [package]
 \
  source1.py [has class that extends SourceBase]
  source2.py
  ...other plugins here...

我的问题是我正在使用以下代码(来自我上面列出的其他堆栈溢出问题)并且它正在我的模块中搜索类,但它没有找到我的类。它只是跳过它们。我不确定出了什么问题。这是我正在执行搜索的代码(它基于我发布的第一个链接):

<!--language: python-->
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)

这是它给我的相关输出(我修剪了这段代码输出的许多其他内容):

Inspecting item from module: source1
Get attribute: <module 'sources.source1' from    '/Users/Mgamerz/Documents/workspace/code/EPDownloader/sources/source1.py'>
[] <--- signifies it failed to find the source class

我很确定我的子类化有效,这是该类的 sn-p:

from EPDownloader import SourceBase
class source1(SourceBase.SourceBase):
    def __init__(self):
        pass

我被这个问题难住了。我已经花了最后几个小时,我不知道该怎么办。我有一种感觉,这是一个我没有看到的简单修复。有人可以帮我找到这里的错误吗?

[注意:我查看了 StackOverflow 格式化帮助,并没有看到任何格式化“突出显示”的方法,即在文本上放置灰色背景但内联的方法。这将有助于突出我试图传达的这个问题的部分内容。]

【问题讨论】:

    标签: python python-3.3


    【解决方案1】:

    查看文档:http://docs.python.org/3.1/library/functions.html#import

    当name变量的形式为package.module时,通常返回顶层包(直到第一个点的名称),而不是名称命名的模块。但是,当给定一个非空的 fromlist 参数时,会返回以 name 命名的模块。

    简单替换

    module=__import__(searchpath+'.'+modname)
    

    module=__import__(searchpath+'.'+modname, None, None, "*")
    

    它与“from sources.source1 import *”相同,它告诉__import__ 获取给定模块内部的所有内容。

    【讨论】:

    • 我不得不调试更多,但你的灵魂奏效了。我已经为此苦恼了好几个小时。谢谢。
    【解决方案2】:

    您的__import__ 有问题:不是导入模块,而是 您正在导入整个包(整个 'sources' 目录作为一个包)。

    我可以修复你的代码:

    for c in candidates:
            modname = os.path.splitext(c)[0]
            print('importing: ',modname)
            # NEW CODE
            sys.path.insert(0, searchpath)
            module=__import__(modname)   #<-- You can get the module this way
            # END OF NEW CODE
            print('Parsing module '+modname)
            ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多