我有一个系统,它收集从某些基类派生的所有类,并将它们存储在字典中。我想避免必须指定哪些类可用(我想以编程方式发现它们),所以使用了from ModuleName import *
语句。然后指示用户将要收集的所有测试放在ModuleName
模块中。但是,我找不到以编程方式确定使用该import语句导入了哪些符号的方法。我已尝试使用dir()
和__dict__
,如以下示例所示,但无济于事。如何以编程方式查找以这种方式导入的符号(使用import *
)?我无法用上述方法找到它们。
testTypeFigureOuterrer.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()
testType1.py:
class TestType1(object):
pass
class TestA(TestType1):
pass
class TestB(TestType1):
pass
testType2.py:
class TestType2:
pass
class TestC(TestType2):
pass
class TestD(TestType2):
pass
答案 0 :(得分:4)
由于您自己了解导入,因此您应该再次手动导入模块,然后检查模块的内容。如果定义了__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('_')]
这样做的好处是您不需要遍历全局变量,并将所有内容过滤掉。既然你知道在设计时导入的模块,你也可以直接检查它们。
from testType1 import *
from testType2 import *
import testType1, testType2
print(getImportedNames(testType1))
print(getImportedNames(testType2))
或者,您也可以通过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'))
答案 1 :(得分:3)
看一下this SO answer,它描述了如何确定加载类的名称,你可以得到模块上下文中定义的所有类的名称。
import sys, inspect
clsmembers = inspect.getmembers(sys.modules['testType1'], inspect.isclass)
现在定义为
[('TestA', testType1.TestA),
('TestB', testType1.TestB),
('TestType1', testType1.TestType1)]
当您处于感兴趣的功能范围内时,您还可以将testType1
替换为__name__
。
答案 2 :(得分:0)
请勿使用*
形式的import
。这会将导入的名称转储到脚本的全局名称空间中。它们不仅可以通过使用相同的名称来破坏一些重要的数据,而且您没有任何简单的方法来删除刚刚导入的名称。 (最简单的方法可能是在前后拍摄globals().keys()
的快照。)
相反,只导入模块:
import testType1
import testType2
现在,您可以轻松获取每个模块中的内容列表:
tests = dir(testType1)
使用模块对象上的getattr()
访问每个:
for testname in tests:
test = getattr(testType1, testname)
if callable(test):
# do something with it