如何以编程方式查找使用Python import*命令导入的符号?

2024-10-01 15:37:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个系统,它收集从某些基类派生的所有类并将它们存储在字典中。我想避免指定哪些类是可用的(我希望通过编程方式发现它们),所以使用了from ModuleName import *语句。然后指示用户将要收集的所有测试放在ModuleName模块中。但是,我找不到一种方法来通过编程来确定导入了哪些符号。我尝试过使用dir()和{},如下面的示例所示,但是没有用。如何通过编程找到以这种方式导入的符号(使用import *)?我用上述方法找不到他们。在

te公司stTypeFigureOutrer.py公司名称:

from testType1 import *
from testType2 import *

class TestFigureOuterrer(object):

    def __init__(self):
        self.existingTests = {'type1':{},'type2':{}}

    def findAndSortTests(self):

        for symbol in dir(): # Also tried: dir(self) and __dict__
            try:
                thing = self.__getattribute__(symbol)
            except AttributeError:
                continue
            if issubclass(thing,TestType1):
                self.existingTests['type1'].update( dict(symbol,thing) )
            elif issubclass(thing,TestType3):
                self.existingTests['type2'].update( dict(symbol,thing) )
            else:
                continue

if __name__ == "__main__":
    testFigureOuterrer = TestFigureOuterrer()
    testFigureOuterrer.findAndSortTests()

测试类型1.py:

^{pr2}$

测试类型2.py:

class TestType2:
    pass

class TestC(TestType2):
    pass

class TestD(TestType2):
    pass

Tags: frompyimportself编程dir方式pass
3条回答

因为您自己知道导入,所以您应该再次手动导入模块,然后检查模块的内容。如果定义了__all__属性,则在from module import *时,其内容将作为名称导入。否则,只需使用其所有成员:

def getImportedNames (module):
    names = module.__all__ if hasattr(module, '__all__') else dir(module)
    return [name for name in names if not name.startswith('_')]

这样做的好处是,您不需要遍历全局,并过滤掉所有内容。而且,由于您知道在设计时从中导入的模块,所以也可以直接检查它们。在

^{pr2}$

或者,也可以通过模块名从sys.modules查找该模块,因此实际上不需要额外的导入:

import sys
def getImportedNames (moduleName):
    module = sys.modules[moduleName]
    names = module.__all__ if hasattr(module, '__all__') else dir(module)
    return [name for name in names if not name.startswith('_')]
print(getImportedNames('testType1'))
print(getImportedNames('testType2'))

不要使用*形式的import。这会将导入的名称转储到脚本的全局命名空间中。它们不仅可以使用相同的名称来删除一些重要的数据,而且还没有任何简单的方法来找出刚刚导入的名称。(最简单的方法可能是拍摄globals().keys()前后的快照。)

相反,只导入模块:

import testType1
import testType2

现在,您可以轻松获得每个模块中的内容列表:

^{pr2}$

并使用模块对象上的getattr()访问每个模块:

for testname in tests:
    test = getattr(testType1, testname)
    if callable(test):
        # do something with it

看看this SO answer,它描述了如何确定加载类的名称,您可以获得在模块上下文中定义的所有类的名称。在

import sys, inspect
clsmembers = inspect.getmembers(sys.modules['testType1'], inspect.isclass)

现在定义为

^{pr2}$

当您在感兴趣的函数中时,也可以将testType1替换为__name__。在

相关问题 更多 >

    热门问题